Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 11365174: A change in the way we place TransitionElementKinds in the tree. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Now includes optimization of codegen for transition elementskind instruction Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 } 588 }
589 589
590 590
591 void LCodeGen::CallCode(Handle<Code> code, 591 void LCodeGen::CallCode(Handle<Code> code,
592 RelocInfo::Mode mode, 592 RelocInfo::Mode mode,
593 LInstruction* instr) { 593 LInstruction* instr) {
594 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); 594 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
595 } 595 }
596 596
597 597
598 void LCodeGen::CallCodeFromDeferred(Handle<Code> code,
599 RelocInfo::Mode mode,
600 LInstruction* instr) {
601 //CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
602
603 ASSERT(instr != NULL);
604 LPointerMap* pointers = instr->pointer_map();
605 RecordPosition(pointers->position());
606 __ call(code, mode);
607 RecordSafepointWithRegisters(
608 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
609
610 // Signal that we don't inline smi code before these stubs in the
611 // optimizing code generator.
612 if (code->kind() == Code::BINARY_OP_IC ||
613 code->kind() == Code::COMPARE_IC) {
614 __ nop();
615 }
616 }
617
618
598 void LCodeGen::CallRuntime(const Runtime::Function* fun, 619 void LCodeGen::CallRuntime(const Runtime::Function* fun,
599 int argc, 620 int argc,
600 LInstruction* instr) { 621 LInstruction* instr) {
601 ASSERT(instr != NULL); 622 ASSERT(instr != NULL);
602 ASSERT(instr->HasPointerMap()); 623 ASSERT(instr->HasPointerMap());
603 LPointerMap* pointers = instr->pointer_map(); 624 LPointerMap* pointers = instr->pointer_map();
604 RecordPosition(pointers->position()); 625 RecordPosition(pointers->position());
605 626
606 __ CallRuntime(fun, argc); 627 __ CallRuntime(fun, argc);
607 628
(...skipping 18 matching lines...) Expand all
626 } else { 647 } else {
627 UNREACHABLE(); 648 UNREACHABLE();
628 } 649 }
629 650
630 __ CallRuntimeSaveDoubles(id); 651 __ CallRuntimeSaveDoubles(id);
631 RecordSafepointWithRegisters( 652 RecordSafepointWithRegisters(
632 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); 653 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
633 } 654 }
634 655
635 656
657 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
658 int argc,
659 LInstruction* instr) {
660 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
661 __ CallRuntimeSaveDoubles(id);
662 RecordSafepointWithRegisters(
663 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
664 }
665
666
636 void LCodeGen::RegisterEnvironmentForDeoptimization( 667 void LCodeGen::RegisterEnvironmentForDeoptimization(
637 LEnvironment* environment, Safepoint::DeoptMode mode) { 668 LEnvironment* environment, Safepoint::DeoptMode mode) {
638 if (!environment->HasBeenRegistered()) { 669 if (!environment->HasBeenRegistered()) {
639 // Physical stack frame layout: 670 // Physical stack frame layout:
640 // -x ............. -4 0 ..................................... y 671 // -x ............. -4 0 ..................................... y
641 // [incoming arguments] [spill slots] [pushed outgoing arguments] 672 // [incoming arguments] [spill slots] [pushed outgoing arguments]
642 673
643 // Layout of the environment: 674 // Layout of the environment:
644 // 0 ..................................................... size-1 675 // 0 ..................................................... size-1
645 // [parameters] [locals] [expression stack including arguments] 676 // [parameters] [locals] [expression stack including arguments]
(...skipping 3404 matching lines...) Expand 10 before | Expand all | Expand 10 after
4050 ASSERT(ToRegister(instr->key()).is(ecx)); 4081 ASSERT(ToRegister(instr->key()).is(ecx));
4051 ASSERT(ToRegister(instr->value()).is(eax)); 4082 ASSERT(ToRegister(instr->value()).is(eax));
4052 4083
4053 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) 4084 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
4054 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 4085 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
4055 : isolate()->builtins()->KeyedStoreIC_Initialize(); 4086 : isolate()->builtins()->KeyedStoreIC_Initialize();
4056 CallCode(ic, RelocInfo::CODE_TARGET, instr); 4087 CallCode(ic, RelocInfo::CODE_TARGET, instr);
4057 } 4088 }
4058 4089
4059 4090
4091 class DeferredTransitionElementsKind: public LDeferredCode {
4092 public:
4093 DeferredTransitionElementsKind(LCodeGen* codegen, LTransitionElementsKind* ins tr)
4094 : LDeferredCode(codegen), instr_(instr) { }
4095 virtual void Generate() { codegen()->DoDeferredTransitionElementsKind(instr_); }
4096 virtual LInstruction* instr() { return instr_; }
4097 private:
4098 LTransitionElementsKind* instr_;
4099 };
4100
4101
4102 void LCodeGen::DoDeferredTransitionElementsKind(LTransitionElementsKind* instr) {
4103 Register object_reg = ToRegister(instr->object());
4104 Handle<Map> to_map = instr->transitioned_map();
4105 ElementsKind to_kind = to_map->elements_kind();
4106
4107 PushSafepointRegistersScope scope(this);
4108
4109 /*
4110 Handle<Code> code = IsFastDoubleElementsKind(to_kind)
4111 ? isolate()->builtins()->TransitionElementsSmiToDouble()
4112 : isolate()->builtins()->TransitionElementsDoubleToObject();
4113
4114 __ mov(ebx, to_map);
4115 if (!edx.is(object_reg)) {
4116 __ mov(edx, object_reg);
4117 }
4118
4119
4120 CallCodeFromDeferred(code,
4121 RelocInfo::CODE_TARGET,
4122 instr);
4123 // RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4124 */
4125
4126 Runtime::FunctionId function_id = IsFastDoubleElementsKind(to_kind)
4127 ? Runtime::kTransitionElementsSmiToDouble
4128 : Runtime::kTransitionElementsDoubleToObject;
4129
4130 __ push(object_reg);
4131 CallRuntimeFromDeferred(function_id, 1, instr);
4132
4133 // __ AssertSmi(eax);
4134 // __ SmiUntag(eax);
4135 __ StoreToSafepointRegisterSlot(object_reg, eax);
4136 }
4137
4138
4060 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 4139 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4061 Register object_reg = ToRegister(instr->object()); 4140 Register object_reg = ToRegister(instr->object());
4062 Register new_map_reg = ToRegister(instr->new_map_temp()); 4141 Register new_map_reg = ToRegister(instr->new_map_temp());
4063 4142
4064 Handle<Map> from_map = instr->original_map(); 4143 Handle<Map> from_map = instr->original_map();
4065 Handle<Map> to_map = instr->transitioned_map(); 4144 Handle<Map> to_map = instr->transitioned_map();
4066 ElementsKind from_kind = from_map->elements_kind(); 4145 ElementsKind from_kind = from_map->elements_kind();
4067 ElementsKind to_kind = to_map->elements_kind(); 4146 ElementsKind to_kind = to_map->elements_kind();
4068 4147
4069 Label not_applicable; 4148 Label not_applicable;
4070 bool is_simple_map_transition = 4149 bool is_simple_map_transition =
4071 IsSimpleMapChangeTransition(from_kind, to_kind); 4150 IsSimpleMapChangeTransition(from_kind, to_kind);
4072 Label::Distance branch_distance = 4151 Label::Distance branch_distance =
4073 is_simple_map_transition ? Label::kNear : Label::kFar; 4152 is_simple_map_transition ? Label::kNear : Label::kFar;
4074 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); 4153 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
4075 __ j(not_equal, &not_applicable, branch_distance); 4154 __ j(not_equal, &not_applicable, branch_distance);
4155
4076 if (is_simple_map_transition) { 4156 if (is_simple_map_transition) {
4077 Register object_reg = ToRegister(instr->object()); 4157 Register object_reg = ToRegister(instr->object());
4078 Handle<Map> map = instr->hydrogen()->transitioned_map(); 4158 Handle<Map> map = instr->hydrogen()->transitioned_map();
4079 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), 4159 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset),
4080 Immediate(map)); 4160 Immediate(map));
4081 // Write barrier. 4161 // Write barrier.
4082 ASSERT_NE(instr->temp(), NULL); 4162 ASSERT_NE(instr->temp(), NULL);
4083 __ RecordWriteForMap(object_reg, to_map, new_map_reg, 4163 __ RecordWriteForMap(object_reg, to_map, new_map_reg,
4084 ToRegister(instr->temp()), 4164 ToRegister(instr->temp()),
4085 kDontSaveFPRegs); 4165 kDontSaveFPRegs);
4086 } else if (IsFastSmiElementsKind(from_kind) && 4166 } else if ((IsFastSmiElementsKind(from_kind) &&
4087 IsFastDoubleElementsKind(to_kind)) { 4167 IsFastDoubleElementsKind(to_kind)) ||
4088 __ mov(new_map_reg, to_map); 4168 (IsFastDoubleElementsKind(from_kind) &&
4089 Register fixed_object_reg = ToRegister(instr->temp()); 4169 IsFastObjectElementsKind(to_kind))) {
4090 ASSERT(fixed_object_reg.is(edx)); 4170 DeferredTransitionElementsKind* deferred =
4091 ASSERT(new_map_reg.is(ebx)); 4171 new(zone()) DeferredTransitionElementsKind(this, instr);
4092 __ mov(fixed_object_reg, object_reg); 4172 __ jmp(deferred->entry());
4093 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), 4173 __ bind(deferred->exit());
4094 RelocInfo::CODE_TARGET, instr);
4095 } else if (IsFastDoubleElementsKind(from_kind) &&
4096 IsFastObjectElementsKind(to_kind)) {
4097 __ mov(new_map_reg, to_map);
4098 Register fixed_object_reg = ToRegister(instr->temp());
4099 ASSERT(fixed_object_reg.is(edx));
4100 ASSERT(new_map_reg.is(ebx));
4101 __ mov(fixed_object_reg, object_reg);
4102 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(),
4103 RelocInfo::CODE_TARGET, instr);
4104 } else { 4174 } else {
4105 UNREACHABLE(); 4175 UNREACHABLE();
4106 } 4176 }
4107 __ bind(&not_applicable); 4177 __ bind(&not_applicable);
4108 } 4178 }
4109 4179
4110 4180
4111 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 4181 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4112 class DeferredStringCharCodeAt: public LDeferredCode { 4182 class DeferredStringCharCodeAt: public LDeferredCode {
4113 public: 4183 public:
(...skipping 1044 matching lines...) Expand 10 before | Expand all | Expand 10 after
5158 } 5228 }
5159 } else { 5229 } else {
5160 UNREACHABLE(); 5230 UNREACHABLE();
5161 } 5231 }
5162 } 5232 }
5163 } 5233 }
5164 5234
5165 5235
5166 void LCodeGen::DoFastLiteral(LFastLiteral* instr) { 5236 void LCodeGen::DoFastLiteral(LFastLiteral* instr) {
5167 ASSERT(ToRegister(instr->context()).is(esi)); 5237 ASSERT(ToRegister(instr->context()).is(esi));
5168 int size = instr->hydrogen()->total_size(); 5238 Handle<JSObject> result = instr->hydrogen()->boilerplate();
5169 ElementsKind boilerplate_elements_kind =
5170 instr->hydrogen()->boilerplate()->GetElementsKind();
5171 5239
5172 // Deopt if the literal boilerplate ElementsKind is of a type different than 5240 if (instr->hydrogen()->TransitionRequested()) {
5173 // the expected one. The check isn't necessary if the boilerplate has already 5241 ElementsKind to_kind = instr->hydrogen()->TransitionTo();
5174 // already been converted to TERMINAL_FAST_ELEMENTS_KIND. 5242 result = Runtime::DeepCopyBoilerplate(isolate(),
5175 if (CanTransitionToMoreGeneralFastElementsKind( 5243 instr->hydrogen()->boilerplate());
5176 boilerplate_elements_kind, true)) { 5244 CHECK(!result.is_null());
5177 __ LoadHeapObject(ebx, instr->hydrogen()->boilerplate()); 5245 // Now transition the copy
5178 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); 5246 CHECK(!JSObject::TransitionElementsKind(result, to_kind).is_null());
5179 // Load the map's "bit field 2". We only need the first byte, 5247 } else {
5180 // but the following masking takes care of that anyway. 5248 // Deopt if the literal boilerplate ElementsKind is of a type different than
5181 __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); 5249 // the expected one. The check isn't necessary if the boilerplate has
5182 // Retrieve elements_kind from bit field 2. 5250 // already already been converted to TERMINAL_FAST_ELEMENTS_KIND.
5183 __ and_(ecx, Map::kElementsKindMask); 5251 ElementsKind boilerplate_elements_kind = result->GetElementsKind();
5184 __ cmp(ecx, boilerplate_elements_kind << Map::kElementsKindShift); 5252 if (CanTransitionToMoreGeneralFastElementsKind(
5185 DeoptimizeIf(not_equal, instr->environment()); 5253 boilerplate_elements_kind, true)) {
5254 __ LoadHeapObject(ebx, result);
5255 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
5256 // Load the map's "bit field 2". We only need the first byte,
5257 // but the following masking takes care of that anyway.
5258 __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset));
5259 // Retrieve elements_kind from bit field 2.
5260 __ and_(ecx, Map::kElementsKindMask);
5261 __ cmp(ecx, boilerplate_elements_kind << Map::kElementsKindShift);
5262 DeoptimizeIf(not_equal, instr->environment());
5263 }
5186 } 5264 }
5187 5265
5188 // Allocate all objects that are part of the literal in one big 5266 // We need to compute the size now.
5267 int size = 0;
5268 int max_properties = HFastLiteral::kMaxLiteralProperties;
5269 HFastLiteral::IsFastLiteral(result,
5270 HFastLiteral::kMaxLiteralDepth,
5271 &max_properties,
5272 &size);
5273
5189 // allocation. This avoids multiple limit checks. 5274 // allocation. This avoids multiple limit checks.
5190 Label allocated, runtime_allocate; 5275 Label allocated, runtime_allocate;
5191 __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); 5276 __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
5192 __ jmp(&allocated); 5277 __ jmp(&allocated);
5193 5278
5194 __ bind(&runtime_allocate); 5279 __ bind(&runtime_allocate);
5195 __ push(Immediate(Smi::FromInt(size))); 5280 __ push(Immediate(Smi::FromInt(size)));
5196 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 5281 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
5197 5282
5198 __ bind(&allocated); 5283 __ bind(&allocated);
5199 int offset = 0; 5284 int offset = 0;
5200 __ LoadHeapObject(ebx, instr->hydrogen()->boilerplate()); 5285 __ LoadHeapObject(ebx, result);
5201 EmitDeepCopy(instr->hydrogen()->boilerplate(), eax, ebx, &offset); 5286 EmitDeepCopy(result, eax, ebx, &offset);
5202 ASSERT_EQ(size, offset); 5287 ASSERT_EQ(size, offset);
5203 } 5288 }
5204 5289
5205 5290
5206 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { 5291 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
5207 ASSERT(ToRegister(instr->context()).is(esi)); 5292 ASSERT(ToRegister(instr->context()).is(esi));
5208 Handle<FixedArray> literals(instr->environment()->closure()->literals()); 5293 Handle<FixedArray> literals(instr->environment()->closure()->literals());
5209 Handle<FixedArray> constant_properties = 5294 Handle<FixedArray> constant_properties =
5210 instr->hydrogen()->constant_properties(); 5295 instr->hydrogen()->constant_properties();
5211 5296
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
5658 FixedArray::kHeaderSize - kPointerSize)); 5743 FixedArray::kHeaderSize - kPointerSize));
5659 __ bind(&done); 5744 __ bind(&done);
5660 } 5745 }
5661 5746
5662 5747
5663 #undef __ 5748 #undef __
5664 5749
5665 } } // namespace v8::internal 5750 } } // namespace v8::internal
5666 5751
5667 #endif // V8_TARGET_ARCH_IA32 5752 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698