From: fschneider@chromium.org Date: Thu, 24 Mar 2011 10:11:51 +0000 (+0000) Subject: Enable GVN for polymorphic loads by not expanding them at the HIR level. X-Git-Tag: upstream/4.7.83~19828 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7d8e6c929d28f37773174b5220f23210e4bf27bb;p=platform%2Fupstream%2Fv8.git Enable GVN for polymorphic loads by not expanding them at the HIR level. This change adds a new IR instruction for polymorphic loads. It performs map compares and loads in one IR instruction instead of splitting each load into a graph of map-compares and field loads. The advantage is a smaller IR and less basic blocks, plus it allows to do GVN on polymorphic loads. Review URL: http://codereview.chromium.org/6708085 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7336 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 3446995..d75794c 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -1769,6 +1769,21 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { } +LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic( + HLoadNamedFieldPolymorphic* instr) { + ASSERT(instr->representation().IsTagged()); + if (instr->need_generic()) { + LOperand* obj = UseFixed(instr->object(), r0); + LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj); + return MarkAsCall(DefineFixed(result, r0), instr); + } else { + LOperand* obj = UseRegisterAtStart(instr->object()); + LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj); + return AssignEnvironment(DefineAsRegister(result)); + } +} + + LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { LOperand* object = UseFixed(instr->object(), r0); LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0); diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index 50650c1..ad80f02 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -123,6 +123,7 @@ class LCodeGen; V(LoadKeyedFastElement) \ V(LoadKeyedGeneric) \ V(LoadNamedField) \ + V(LoadNamedFieldPolymorphic) \ V(LoadNamedGeneric) \ V(LoadPixelArrayElement) \ V(ModI) \ @@ -1148,6 +1149,19 @@ class LLoadNamedField: public LTemplateInstruction<1, 1, 0> { }; +class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> { + public: + explicit LLoadNamedFieldPolymorphic(LOperand* object) { + inputs_[0] = object; + } + + DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic") + DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic) + + LOperand* object() { return inputs_[0]; } +}; + + class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> { public: explicit LLoadNamedGeneric(LOperand* object) { diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index cc93101..09c83a5 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -2203,6 +2203,70 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { } +void LCodeGen::EmitLoadField(Register result, + Register object, + Handle type, + Handle name) { + LookupResult lookup; + type->LookupInDescriptors(NULL, *name, &lookup); + ASSERT(lookup.IsProperty() && lookup.type() == FIELD); + int index = lookup.GetLocalFieldIndexFromMap(*type); + int offset = index * kPointerSize; + if (index < 0) { + // Negative property indices are in-object properties, indexed + // from the end of the fixed part of the object. + __ ldr(result, FieldMemOperand(object, offset + type->instance_size())); + } else { + // Non-negative property indices are in the properties array. + __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); + __ ldr(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize)); + } +} + + +void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { + Register object = ToRegister(instr->object()); + Register result = ToRegister(instr->result()); + Register scratch = scratch0(); + int map_count = instr->hydrogen()->types()->length(); + Handle name = instr->hydrogen()->name(); + if (map_count == 0) { + ASSERT(instr->hydrogen()->need_generic()); + __ mov(r2, Operand(name)); + Handle ic = isolate()->builtins()->LoadIC_Initialize(); + CallCode(ic, RelocInfo::CODE_TARGET, instr); + } else { + Label done; + __ ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); + for (int i = 0; i < map_count - 1; ++i) { + Handle map = instr->hydrogen()->types()->at(i); + Label next; + __ cmp(scratch, Operand(map)); + __ b(ne, &next); + EmitLoadField(result, object, map, name); + __ b(&done); + __ bind(&next); + } + Handle map = instr->hydrogen()->types()->last(); + __ cmp(scratch, Operand(map)); + if (instr->hydrogen()->need_generic()) { + Label generic; + __ b(ne, &generic); + EmitLoadField(result, object, map, name); + __ b(&done); + __ bind(&generic); + __ mov(r2, Operand(name)); + Handle ic = isolate()->builtins()->LoadIC_Initialize(); + CallCode(ic, RelocInfo::CODE_TARGET, instr); + } else { + DeoptimizeIf(ne, instr->environment()); + EmitLoadField(result, object, map, name); + } + __ bind(&done); + } +} + + void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { ASSERT(ToRegister(instr->object()).is(r0)); ASSERT(ToRegister(instr->result()).is(r0)); diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h index da34176..caa85d2 100644 --- a/src/arm/lithium-codegen-arm.h +++ b/src/arm/lithium-codegen-arm.h @@ -264,6 +264,11 @@ class LCodeGen BASE_EMBEDDED { // Caller should branch on equal condition. void EmitIsConstructCall(Register temp1, Register temp2); + void EmitLoadField(Register result, + Register object, + Handle type, + Handle name); + LChunk* const chunk_; MacroAssembler* const masm_; CompilationInfo* const info_; diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index e253795..bd6a58b 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -1156,6 +1156,60 @@ void HLoadNamedField::PrintDataTo(StringStream* stream) { } +HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* object, + ZoneMapList* types, + Handle name) + : HUnaryOperation(object), + types_(Min(types->length(), kMaxLoadPolymorphism)), + name_(name), + need_generic_(false) { + set_representation(Representation::Tagged()); + SetFlag(kDependsOnMaps); + for (int i = 0; + i < types->length() && types_.length() < kMaxLoadPolymorphism; + ++i) { + Handle map = types->at(i); + LookupResult lookup; + map->LookupInDescriptors(NULL, *name, &lookup); + if (lookup.IsProperty() && lookup.type() == FIELD) { + types_.Add(types->at(i)); + int index = lookup.GetLocalFieldIndexFromMap(*map); + if (index < 0) { + SetFlag(kDependsOnInobjectFields); + } else { + SetFlag(kDependsOnBackingStoreFields); + } + } + } + + if (types_.length() == types->length() && FLAG_deoptimize_uncommon_cases) { + SetFlag(kUseGVN); + } else { + SetAllSideEffects(); + need_generic_ = true; + } +} + + +bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) { + HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value); + if (types_.length() != other->types()->length()) return false; + if (!name_.is_identical_to(other->name())) return false; + if (need_generic_ != other->need_generic_) return false; + for (int i = 0; i < types_.length(); i++) { + bool found = false; + for (int j = 0; j < types_.length(); j++) { + if (types_.at(j).is_identical_to(other->types()->at(i))) { + found = true; + break; + } + } + if (!found) return false; + } + return true; +} + + void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) { object()->PrintNameTo(stream); stream->Add("["); diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index c08540f..ed78040 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -129,6 +129,7 @@ class LChunkBuilder; V(LoadKeyedGeneric) \ V(LoadNamedField) \ V(LoadNamedGeneric) \ + V(LoadNamedFieldPolymorphic) \ V(LoadPixelArrayElement) \ V(Mod) \ V(Mul) \ @@ -2972,6 +2973,37 @@ class HLoadNamedField: public HUnaryOperation { }; +class HLoadNamedFieldPolymorphic: public HUnaryOperation { + public: + HLoadNamedFieldPolymorphic(HValue* object, + ZoneMapList* types, + Handle name); + + HValue* object() { return OperandAt(0); } + ZoneMapList* types() { return &types_; } + Handle name() { return name_; } + bool need_generic() { return need_generic_; } + + virtual Representation RequiredInputRepresentation(int index) const { + return Representation::Tagged(); + } + + DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic, + "load_named_field_polymorphic") + + static const int kMaxLoadPolymorphism = 4; + + protected: + virtual bool DataEquals(HValue* value); + + private: + ZoneMapList types_; + Handle name_; + bool need_generic_; +}; + + + class HLoadNamedGeneric: public HBinaryOperation { public: HLoadNamedGeneric(HValue* context, HValue* object, Handle name) diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 28a8908..17f27fd 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -3445,69 +3445,6 @@ void HGraphBuilder::VisitThrow(Throw* expr) { } -void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, - HValue* object, - ZoneMapList* types, - Handle name) { - // TODO(ager): We should recognize when the prototype chains for different - // maps are identical. In that case we can avoid repeatedly generating the - // same prototype map checks. - int count = 0; - HBasicBlock* join = NULL; - for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { - Handle map = types->at(i); - LookupResult lookup; - map->LookupInDescriptors(NULL, *name, &lookup); - if (lookup.IsProperty() && lookup.type() == FIELD) { - if (count == 0) { - AddInstruction(new HCheckNonSmi(object)); // Only needed once. - join = graph()->CreateBasicBlock(); - } - ++count; - HBasicBlock* if_true = graph()->CreateBasicBlock(); - HBasicBlock* if_false = graph()->CreateBasicBlock(); - HCompareMap* compare = new HCompareMap(object, map, if_true, if_false); - current_block()->Finish(compare); - - set_current_block(if_true); - HLoadNamedField* instr = - BuildLoadNamedField(object, expr, map, &lookup, false); - instr->set_position(expr->position()); - instr->ClearFlag(HValue::kUseGVN); - AddInstruction(instr); - if (!ast_context()->IsEffect()) Push(instr); - current_block()->Goto(join); - - set_current_block(if_false); - } - } - - // Finish up. Unconditionally deoptimize if we've handled all the maps we - // know about and do not want to handle ones we've never seen. Otherwise - // use a generic IC. - if (count == types->length() && FLAG_deoptimize_uncommon_cases) { - current_block()->FinishExitWithDeoptimization(); - } else { - HInstruction* instr = BuildLoadNamedGeneric(object, expr); - instr->set_position(expr->position()); - - if (join != NULL) { - AddInstruction(instr); - if (!ast_context()->IsEffect()) Push(instr); - current_block()->Goto(join); - } else { - ast_context()->ReturnInstruction(instr, expr->id()); - return; - } - } - - ASSERT(join != NULL); - join->SetJoinId(expr->id()); - set_current_block(join); - if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); -} - - HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, Property* expr, Handle type, @@ -3748,9 +3685,8 @@ void HGraphBuilder::VisitProperty(Property* expr) { if (expr->IsMonomorphic()) { instr = BuildLoadNamed(obj, expr, types->first(), name); } else if (types != NULL && types->length() > 1) { - HandlePolymorphicLoadNamedField(expr, obj, types, name); - return; - + AddInstruction(new HCheckNonSmi(obj)); + instr = new HLoadNamedFieldPolymorphic(obj, types, name); } else { instr = BuildLoadNamedGeneric(obj, expr); } diff --git a/src/hydrogen.h b/src/hydrogen.h index dee7866..34115337 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -794,10 +794,6 @@ class HGraphBuilder: public AstVisitor { void HandlePropertyAssignment(Assignment* expr); void HandleCompoundAssignment(Assignment* expr); - void HandlePolymorphicLoadNamedField(Property* expr, - HValue* object, - ZoneMapList* types, - Handle name); void HandlePolymorphicStoreNamedField(Assignment* expr, HValue* object, HValue* value, diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index a3c0990..84eb799 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -2109,7 +2109,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { - Register object = ToRegister(instr->InputAt(0)); + Register object = ToRegister(instr->object()); Register result = ToRegister(instr->result()); if (instr->hydrogen()->is_in_object()) { __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); @@ -2120,6 +2120,69 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { } +void LCodeGen::EmitLoadField(Register result, + Register object, + Handle type, + Handle name) { + LookupResult lookup; + type->LookupInDescriptors(NULL, *name, &lookup); + ASSERT(lookup.IsProperty() && lookup.type() == FIELD); + int index = lookup.GetLocalFieldIndexFromMap(*type); + int offset = index * kPointerSize; + if (index < 0) { + // Negative property indices are in-object properties, indexed + // from the end of the fixed part of the object. + __ mov(result, FieldOperand(object, offset + type->instance_size())); + } else { + // Non-negative property indices are in the properties array. + __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); + __ mov(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); + } +} + + +void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { + Register object = ToRegister(instr->object()); + Register result = ToRegister(instr->result()); + + int map_count = instr->hydrogen()->types()->length(); + Handle name = instr->hydrogen()->name(); + if (map_count == 0) { + ASSERT(instr->hydrogen()->need_generic()); + __ mov(ecx, name); + Handle ic = isolate()->builtins()->LoadIC_Initialize(); + CallCode(ic, RelocInfo::CODE_TARGET, instr, false); + } else { + NearLabel done; + for (int i = 0; i < map_count - 1; ++i) { + Handle map = instr->hydrogen()->types()->at(i); + NearLabel next; + __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); + __ j(not_equal, &next); + EmitLoadField(result, object, map, name); + __ jmp(&done); + __ bind(&next); + } + Handle map = instr->hydrogen()->types()->last(); + __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); + if (instr->hydrogen()->need_generic()) { + NearLabel generic; + __ j(not_equal, &generic); + EmitLoadField(result, object, map, name); + __ jmp(&done); + __ bind(&generic); + __ mov(ecx, name); + Handle ic = isolate()->builtins()->LoadIC_Initialize(); + CallCode(ic, RelocInfo::CODE_TARGET, instr, false); + } else { + DeoptimizeIf(not_equal, instr->environment()); + EmitLoadField(result, object, map, name); + } + __ bind(&done); + } +} + + void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { ASSERT(ToRegister(instr->context()).is(esi)); ASSERT(ToRegister(instr->object()).is(eax)); diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h index d06603c..4414e6a 100644 --- a/src/ia32/lithium-codegen-ia32.h +++ b/src/ia32/lithium-codegen-ia32.h @@ -246,6 +246,10 @@ class LCodeGen BASE_EMBEDDED { // Caller should branch on equal condition. void EmitIsConstructCall(Register temp); + void EmitLoadField(Register result, + Register object, + Handle type, + Handle name); LChunk* const chunk_; MacroAssembler* const masm_; diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 96b7937..0383d72 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -1790,6 +1790,21 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { } +LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic( + HLoadNamedFieldPolymorphic* instr) { + ASSERT(instr->representation().IsTagged()); + if (instr->need_generic()) { + LOperand* obj = UseFixed(instr->object(), eax); + LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj); + return MarkAsCall(DefineFixed(result, eax), instr); + } else { + LOperand* obj = UseRegisterAtStart(instr->object()); + LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj); + return AssignEnvironment(DefineAsRegister(result)); + } +} + + LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { LOperand* context = UseFixed(instr->context(), esi); LOperand* object = UseFixed(instr->object(), eax); diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index 70ec962..02735b6 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -125,6 +125,7 @@ class LCodeGen; V(LoadKeyedFastElement) \ V(LoadKeyedGeneric) \ V(LoadNamedField) \ + V(LoadNamedFieldPolymorphic) \ V(LoadNamedGeneric) \ V(LoadPixelArrayElement) \ V(ModI) \ @@ -1171,6 +1172,21 @@ class LLoadNamedField: public LTemplateInstruction<1, 1, 0> { DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field") DECLARE_HYDROGEN_ACCESSOR(LoadNamedField) + + LOperand* object() { return inputs_[0]; } +}; + + +class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> { + public: + explicit LLoadNamedFieldPolymorphic(LOperand* object) { + inputs_[0] = object; + } + + DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic") + DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic) + + LOperand* object() { return inputs_[0]; } }; diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 3745d16..af072fd 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -2091,6 +2091,70 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { } +void LCodeGen::EmitLoadField(Register result, + Register object, + Handle type, + Handle name) { + LookupResult lookup; + type->LookupInDescriptors(NULL, *name, &lookup); + ASSERT(lookup.IsProperty() && lookup.type() == FIELD); + int index = lookup.GetLocalFieldIndexFromMap(*type); + int offset = index * kPointerSize; + if (index < 0) { + // Negative property indices are in-object properties, indexed + // from the end of the fixed part of the object. + __ movq(result, FieldOperand(object, offset + type->instance_size())); + } else { + // Non-negative property indices are in the properties array. + __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); + __ movq(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); + } +} + + +void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { + Register object = ToRegister(instr->object()); + Register result = ToRegister(instr->result()); + + int map_count = instr->hydrogen()->types()->length(); + Handle name = instr->hydrogen()->name(); + + if (map_count == 0) { + ASSERT(instr->hydrogen()->need_generic()); + __ Move(rcx, instr->hydrogen()->name()); + Handle ic = isolate()->builtins()->LoadIC_Initialize(); + CallCode(ic, RelocInfo::CODE_TARGET, instr); + } else { + NearLabel done; + for (int i = 0; i < map_count - 1; ++i) { + Handle map = instr->hydrogen()->types()->at(i); + NearLabel next; + __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); + __ j(not_equal, &next); + EmitLoadField(result, object, map, name); + __ jmp(&done); + __ bind(&next); + } + Handle map = instr->hydrogen()->types()->last(); + __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); + if (instr->hydrogen()->need_generic()) { + NearLabel generic; + __ j(not_equal, &generic); + EmitLoadField(result, object, map, name); + __ jmp(&done); + __ bind(&generic); + __ Move(rcx, instr->hydrogen()->name()); + Handle ic = isolate()->builtins()->LoadIC_Initialize(); + CallCode(ic, RelocInfo::CODE_TARGET, instr); + } else { + DeoptimizeIf(not_equal, instr->environment()); + EmitLoadField(result, object, map, name); + } + __ bind(&done); + } +} + + void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { ASSERT(ToRegister(instr->object()).is(rax)); ASSERT(ToRegister(instr->result()).is(rax)); diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h index fcd0a70..f44fdb9 100644 --- a/src/x64/lithium-codegen-x64.h +++ b/src/x64/lithium-codegen-x64.h @@ -241,6 +241,11 @@ class LCodeGen BASE_EMBEDDED { // Caller should branch on equal condition. void EmitIsConstructCall(Register temp); + void EmitLoadField(Register result, + Register object, + Handle type, + Handle name); + // Emits code for pushing a constant operand. void EmitPushConstantOperand(LOperand* operand); diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 09b7b63..9e72731 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1763,6 +1763,21 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { } +LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic( + HLoadNamedFieldPolymorphic* instr) { + ASSERT(instr->representation().IsTagged()); + if (instr->need_generic()) { + LOperand* obj = UseFixed(instr->object(), rax); + LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj); + return MarkAsCall(DefineFixed(result, rax), instr); + } else { + LOperand* obj = UseRegisterAtStart(instr->object()); + LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj); + return AssignEnvironment(DefineAsRegister(result)); + } +} + + LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { LOperand* object = UseFixed(instr->object(), rax); LLoadNamedGeneric* result = new LLoadNamedGeneric(object); diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h index f5c3ddd..4b26487 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h @@ -122,6 +122,7 @@ class LCodeGen; V(LoadKeyedFastElement) \ V(LoadKeyedGeneric) \ V(LoadNamedField) \ + V(LoadNamedFieldPolymorphic) \ V(LoadNamedGeneric) \ V(LoadFunctionPrototype) \ V(LoadPixelArrayElement) \ @@ -1134,6 +1135,19 @@ class LLoadNamedField: public LTemplateInstruction<1, 1, 0> { }; +class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> { + public: + explicit LLoadNamedFieldPolymorphic(LOperand* object) { + inputs_[0] = object; + } + + DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic") + DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic) + + LOperand* object() { return inputs_[0]; } +}; + + class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> { public: explicit LLoadNamedGeneric(LOperand* object) {