Revision: 16133
Author: [email protected]
Date: Fri Aug 9 07:04:47 2013
Log: Replace LoadNamedFieldPolymorphic with explicit branches.
[email protected]
Review URL: https://chromiumcodereview.appspot.com/22213002
http://code.google.com/p/v8/source/detail?r=16133
Added:
/branches/bleeding_edge/test/mjsunit/load_poly_effect.js
Modified:
/branches/bleeding_edge/src/arm/lithium-arm.cc
/branches/bleeding_edge/src/arm/lithium-arm.h
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/arm/lithium-codegen-arm.h
/branches/bleeding_edge/src/hydrogen-instructions.cc
/branches/bleeding_edge/src/hydrogen-instructions.h
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h
/branches/bleeding_edge/src/ia32/lithium-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-ia32.h
/branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
/branches/bleeding_edge/src/x64/lithium-codegen-x64.h
/branches/bleeding_edge/src/x64/lithium-x64.cc
/branches/bleeding_edge/src/x64/lithium-x64.h
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/load_poly_effect.js Fri Aug 9
07:04:47 2013
@@ -0,0 +1,47 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+var o = {};
+var count = 0;
+Object.defineProperty(o, "x", {get:function(){count++;return 100}});
+
+function load(o, o2) {
+ return 1 + (o.x, o2.x_tagged);
+}
+
+var deopt = false;
+var o2 = {x_tagged:{}};
+o2.x_tagged = 1;
+
+load({x:1}, o2);
+load({x:1}, o2);
+print(load(o, o2));
+%OptimizeFunctionOnNextCall(load);
+o2.x_tagged = true;
+print(load(o, o2));
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Wed Aug 7 19:16:12 2013
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc Fri Aug 9 07:04:47 2013
@@ -2145,23 +2145,6 @@
LOperand* obj = UseRegisterAtStart(instr->object());
return DefineAsRegister(new(zone()) LLoadNamedField(obj));
}
-
-
-LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
- HLoadNamedFieldPolymorphic* instr) {
- ASSERT(instr->representation().IsTagged());
- if (instr->need_generic()) {
- LOperand* obj = UseFixed(instr->object(), r0);
- LLoadNamedFieldPolymorphic* result =
- new(zone()) LLoadNamedFieldPolymorphic(obj);
- return MarkAsCall(DefineFixed(result, r0), instr);
- } else {
- LOperand* obj = UseRegisterAtStart(instr->object());
- LLoadNamedFieldPolymorphic* result =
- new(zone()) LLoadNamedFieldPolymorphic(obj);
- return AssignEnvironment(DefineAsRegister(result));
- }
-}
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h Wed Aug 7 19:16:12 2013
+++ /branches/bleeding_edge/src/arm/lithium-arm.h Fri Aug 9 07:04:47 2013
@@ -126,7 +126,6 @@
V(LoadKeyed) \
V(LoadKeyedGeneric) \
V(LoadNamedField) \
- V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
V(MapEnumLength) \
V(MathAbs) \
@@ -1527,19 +1526,6 @@
};
-class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> {
- public:
- explicit LLoadNamedFieldPolymorphic(LOperand* object) {
- inputs_[0] = object;
- }
-
- LOperand* object() { return inputs_[0]; }
-
-
DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic")
- DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic)
-};
-
-
class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> {
public:
explicit LLoadNamedGeneric(LOperand* object) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Aug 9
05:50:42 2013
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Aug 9
07:04:47 2013
@@ -3050,91 +3050,6 @@
__ ldr(result, FieldMemOperand(result, offset));
}
}
-
-
-void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
- Register object,
- Handle<Map> type,
- Handle<String> name,
- LEnvironment* env) {
- LookupResult lookup(isolate());
- type->LookupDescriptor(NULL, *name, &lookup);
- ASSERT(lookup.IsFound() || lookup.IsCacheable());
- if (lookup.IsField()) {
- 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));
- }
- } else if (lookup.IsConstant()) {
- Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
- __ LoadObject(result, constant);
- } else {
- // Negative lookup.
- // Check prototypes.
- Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
- Heap* heap = type->GetHeap();
- while (*current != heap->null_value()) {
- __ LoadHeapObject(result, current);
- __ ldr(result, FieldMemOperand(result, HeapObject::kMapOffset));
- __ cmp(result, Operand(Handle<Map>(current->map())));
- DeoptimizeIf(ne, env);
- current =
-
Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
- }
- __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
- }
-}
-
-
-void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic*
instr) {
- Register object = ToRegister(instr->object());
- Register result = ToRegister(instr->result());
- Register object_map = scratch0();
-
- int map_count = instr->hydrogen()->types()->length();
- bool need_generic = instr->hydrogen()->need_generic();
-
- if (map_count == 0 && !need_generic) {
- DeoptimizeIf(al, instr->environment());
- return;
- }
- Handle<String> name = instr->hydrogen()->name();
- Label done;
- __ ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
- for (int i = 0; i < map_count; ++i) {
- bool last = (i == map_count - 1);
- Handle<Map> map = instr->hydrogen()->types()->at(i);
- Label check_passed;
- __ CompareMap(object_map, map, &check_passed);
- if (last && !need_generic) {
- DeoptimizeIf(ne, instr->environment());
- __ bind(&check_passed);
- EmitLoadFieldOrConstantFunction(
- result, object, map, name, instr->environment());
- } else {
- Label next;
- __ b(ne, &next);
- __ bind(&check_passed);
- EmitLoadFieldOrConstantFunction(
- result, object, map, name, instr->environment());
- __ b(&done);
- __ bind(&next);
- }
- }
- if (need_generic) {
- __ mov(r2, Operand(name));
- Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
- CallCode(ic, RelocInfo::CODE_TARGET, instr,
NEVER_INLINE_TARGET_ADDRESS);
- }
- __ bind(&done);
-}
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Wed Aug 7
19:16:12 2013
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Fri Aug 9
07:04:47 2013
@@ -360,12 +360,6 @@
// Caller should branch on equal condition.
void EmitIsConstructCall(Register temp1, Register temp2);
- void EmitLoadFieldOrConstantFunction(Register result,
- Register object,
- Handle<Map> type,
- Handle<String> name,
- LEnvironment* env);
-
// Emits optimized code to deep-copy the contents of statically known
// object graphs (e.g. object literal boilerplate).
void EmitDeepCopy(Handle<JSObject> object,
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Fri Aug 9
05:33:06 2013
+++ /branches/bleeding_edge/src/hydrogen-instructions.cc Fri Aug 9
07:04:47 2013
@@ -2842,119 +2842,6 @@
typecheck()->PrintNameTo(stream);
}
}
-
-
-// Returns true if an instance of this map can never find a property with
this
-// name in its prototype chain. This means all prototypes up to the top
are
-// fast and don't have the name in them. It would be good if we could
optimize
-// polymorphic loads where the property is sometimes found in the prototype
-// chain.
-static bool PrototypeChainCanNeverResolve(
- Handle<Map> map, Handle<String> name) {
- Isolate* isolate = map->GetIsolate();
- Object* current = map->prototype();
- while (current != isolate->heap()->null_value()) {
- if (current->IsJSGlobalProxy() ||
- current->IsGlobalObject() ||
- !current->IsJSObject() ||
- JSObject::cast(current)->map()->has_named_interceptor() ||
- JSObject::cast(current)->IsAccessCheckNeeded() ||
- !JSObject::cast(current)->HasFastProperties()) {
- return false;
- }
-
- LookupResult lookup(isolate);
- Map* map = JSObject::cast(current)->map();
- map->LookupDescriptor(NULL, *name, &lookup);
- if (lookup.IsFound()) return false;
- if (!lookup.IsCacheable()) return false;
- current = JSObject::cast(current)->GetPrototype();
- }
- return true;
-}
-
-
-HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
- HValue* object,
- SmallMapList* types,
- Handle<String> name,
- Zone* zone)
- : types_(Min(types->length(), kMaxLoadPolymorphism), zone),
- name_(name),
- types_unique_ids_(0, zone),
- name_unique_id_(),
- need_generic_(false) {
- SetOperandAt(0, context);
- SetOperandAt(1, object);
- set_representation(Representation::Tagged());
- SetGVNFlag(kDependsOnMaps);
- SmallMapList negative_lookups;
- for (int i = 0;
- i < types->length() && types_.length() < kMaxLoadPolymorphism;
- ++i) {
- Handle<Map> map = types->at(i);
- // Deprecated maps are updated to the current map in the type oracle.
- ASSERT(!map->is_deprecated());
- LookupResult lookup(map->GetIsolate());
- map->LookupDescriptor(NULL, *name, &lookup);
- if (lookup.IsFound()) {
- switch (lookup.type()) {
- case FIELD: {
- int index = lookup.GetLocalFieldIndexFromMap(*map);
- if (index < 0) {
- SetGVNFlag(kDependsOnInobjectFields);
- } else {
- SetGVNFlag(kDependsOnBackingStoreFields);
- }
- if (FLAG_track_double_fields &&
- lookup.representation().IsDouble()) {
- // Since the value needs to be boxed, use a generic handler for
- // loading doubles.
- continue;
- }
- types_.Add(types->at(i), zone);
- break;
- }
- case CONSTANT:
- types_.Add(types->at(i), zone);
- break;
- case CALLBACKS:
- break;
- case TRANSITION:
- case INTERCEPTOR:
- case NONEXISTENT:
- case NORMAL:
- case HANDLER:
- UNREACHABLE();
- break;
- }
- } else if (lookup.IsCacheable() &&
- // For dicts the lookup on the map will fail, but the
object may
- // contain the property so we cannot generate a negative
lookup
- // (which would just be a map check and return undefined).
- !map->is_dictionary_map() &&
- !map->has_named_interceptor() &&
- PrototypeChainCanNeverResolve(map, name)) {
- negative_lookups.Add(types->at(i), zone);
- }
- }
-
- bool need_generic =
- (types->length() != negative_lookups.length() + types_.length());
- if (!need_generic && FLAG_deoptimize_uncommon_cases) {
- SetFlag(kUseGVN);
- for (int i = 0; i < negative_lookups.length(); i++) {
- types_.Add(negative_lookups.at(i), zone);
- }
- } else {
- // We don't have an easy way to handle both a call (to the generic
stub) and
- // a deopt in the same hydrogen instruction, so in this case we don't
add
- // the negative lookups which can deopt - just let the generic stub
handle
- // them.
- SetAllSideEffects();
- need_generic_ = true;
- }
-}
HCheckMaps* HCheckMaps::New(Zone* zone,
@@ -2983,46 +2870,6 @@
map_unique_ids_.Add(UniqueValueId(map_set_.at(i)), zone);
}
}
-
-
-void HLoadNamedFieldPolymorphic::FinalizeUniqueValueId() {
- if (!types_unique_ids_.is_empty()) return;
- Zone* zone = block()->zone();
- types_unique_ids_.Initialize(types_.length(), zone);
- for (int i = 0; i < types_.length(); i++) {
- types_unique_ids_.Add(UniqueValueId(types_.at(i)), zone);
- }
- name_unique_id_ = UniqueValueId(name_);
-}
-
-
-bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
- ASSERT_EQ(types_.length(), types_unique_ids_.length());
- HLoadNamedFieldPolymorphic* other =
HLoadNamedFieldPolymorphic::cast(value);
- if (name_unique_id_ != other->name_unique_id_) return false;
- if (types_unique_ids_.length() != other->types_unique_ids_.length()) {
- return false;
- }
- if (need_generic_ != other->need_generic_) return false;
- for (int i = 0; i < types_unique_ids_.length(); i++) {
- bool found = false;
- for (int j = 0; j < types_unique_ids_.length(); j++) {
- if (types_unique_ids_.at(j) == other->types_unique_ids_.at(i)) {
- found = true;
- break;
- }
- }
- if (!found) return false;
- }
- return true;
-}
-
-
-void HLoadNamedFieldPolymorphic::PrintDataTo(StringStream* stream) {
- object()->PrintNameTo(stream);
- stream->Add(".");
- stream->Add(*String::cast(*name())->ToCString());
-}
void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Fri Aug 9 05:50:42
2013
+++ /branches/bleeding_edge/src/hydrogen-instructions.h Fri Aug 9 07:04:47
2013
@@ -142,7 +142,6 @@
V(LoadKeyed) \
V(LoadKeyedGeneric) \
V(LoadNamedField) \
- V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
V(MapEnumLength) \
V(MathFloorOfDiv) \
@@ -5622,45 +5621,6 @@
};
-class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
- public:
- HLoadNamedFieldPolymorphic(HValue* context,
- HValue* object,
- SmallMapList* types,
- Handle<String> name,
- Zone* zone);
-
- HValue* context() { return OperandAt(0); }
- HValue* object() { return OperandAt(1); }
- SmallMapList* types() { return &types_; }
- Handle<String> name() { return name_; }
- bool need_generic() { return need_generic_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
-
- static const int kMaxLoadPolymorphism = 4;
-
- virtual void FinalizeUniqueValueId();
-
- protected:
- virtual bool DataEquals(HValue* value);
-
- private:
- SmallMapList types_;
- Handle<String> name_;
- ZoneList<UniqueValueId> types_unique_ids_;
- UniqueValueId name_unique_id_;
- bool need_generic_;
-};
-
-
-
class HLoadNamedGeneric: public HTemplateInstruction<2> {
public:
HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Fri Aug 9 05:50:42 2013
+++ /branches/bleeding_edge/src/hydrogen.cc Fri Aug 9 07:04:47 2013
@@ -4599,6 +4599,36 @@
return BuildLoadNamedField(holder_value,
HObjectAccess::ForField(holder_map, &lookup, name));
}
+
+
+// Returns true if an instance of this map can never find a property with
this
+// name in its prototype chain. This means all prototypes up to the top
are
+// fast and don't have the name in them. It would be good if we could
optimize
+// polymorphic loads where the property is sometimes found in the prototype
+// chain.
+static bool PrototypeChainCanNeverResolve(
+ Handle<Map> map, Handle<String> name) {
+ Isolate* isolate = map->GetIsolate();
+ Object* current = map->prototype();
+ while (current != isolate->heap()->null_value()) {
+ if (current->IsJSGlobalProxy() ||
+ current->IsGlobalObject() ||
+ !current->IsJSObject() ||
+ JSObject::cast(current)->map()->has_named_interceptor() ||
+ JSObject::cast(current)->IsAccessCheckNeeded() ||
+ !JSObject::cast(current)->HasFastProperties()) {
+ return false;
+ }
+
+ LookupResult lookup(isolate);
+ Map* map = JSObject::cast(current)->map();
+ map->LookupDescriptor(NULL, *name, &lookup);
+ if (lookup.IsFound()) return false;
+ if (!lookup.IsCacheable()) return false;
+ current = JSObject::cast(current)->GetPrototype();
+ }
+ return true;
+}
void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
@@ -4608,16 +4638,90 @@
Handle<String> name) {
HInstruction* instr = TryLoadPolymorphicAsMonomorphic(
expr, object, types, name);
- if (instr == NULL) {
- // Something did not match; must use a polymorphic load.
- BuildCheckHeapObject(object);
- HValue* context = environment()->context();
- instr = new(zone()) HLoadNamedFieldPolymorphic(
- context, object, types, name, zone());
+ if (instr != NULL) {
+ instr->set_position(expr->position());
+ return ast_context()->ReturnInstruction(instr, expr->id());
}
- instr->set_position(expr->position());
- return ast_context()->ReturnInstruction(instr, expr->id());
+ // Something did not match; must use a polymorphic load.
+ int count = 0;
+ HBasicBlock* join = NULL;
+ for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism;
++i) {
+ Handle<Map> map = types->at(i);
+ LookupResult lookup(isolate());
+ if (ComputeLoadStoreField(map, name, &lookup, false) ||
+ (lookup.IsCacheable() &&
+ !map->is_dictionary_map() &&
+ !map->has_named_interceptor() &&
+ (lookup.IsConstant() ||
+ (!lookup.IsFound() &&
+ PrototypeChainCanNeverResolve(map, name))))) {
+ if (count == 0) {
+ BuildCheckHeapObject(object);
+ join = graph()->CreateBasicBlock();
+ }
+ ++count;
+ HBasicBlock* if_true = graph()->CreateBasicBlock();
+ HBasicBlock* if_false = graph()->CreateBasicBlock();
+ HCompareMap* compare =
+ new(zone()) HCompareMap(object, map, if_true, if_false);
+ current_block()->Finish(compare);
+
+ set_current_block(if_true);
+
+ // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic.
+ if (lookup.IsField()) {
+ HObjectAccess access = HObjectAccess::ForField(map, &lookup, name);
+ HLoadNamedField* load = BuildLoadNamedField(object, access);
+ load->set_position(expr->position());
+ AddInstruction(load);
+ if (!ast_context()->IsEffect()) Push(load);
+ } else if (lookup.IsConstant()) {
+ Handle<Object> constant(lookup.GetConstantFromMap(*map),
isolate());
+ HConstant* hconstant = Add<HConstant>(constant);
+ if (!ast_context()->IsEffect()) Push(hconstant);
+ } else {
+ ASSERT(!lookup.IsFound());
+ if (map->prototype()->IsJSObject()) {
+ Handle<JSObject> prototype(JSObject::cast(map->prototype()));
+ Handle<JSObject> holder = prototype;
+ while (holder->map()->prototype()->IsJSObject()) {
+ holder = handle(JSObject::cast(holder->map()->prototype()));
+ }
+ BuildCheckPrototypeMaps(prototype, holder);
+ }
+ if (!ast_context()->IsEffect())
Push(graph()->GetConstantUndefined());
+ }
+
+ 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) {
+ FinishExitWithHardDeoptimization("Unknown map in polymorphic load",
join);
+ } else {
+ HInstruction* load = BuildLoadNamedGeneric(object, name, expr);
+ load->set_position(expr->position());
+ AddInstruction(load);
+ if (!ast_context()->IsEffect()) Push(load);
+
+ if (join != NULL) {
+ current_block()->Goto(join);
+ } else {
+ Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
+ if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
+ return;
+ }
+ }
+
+ ASSERT(join != NULL);
+ join->SetJoinId(expr->id());
+ set_current_block(join);
+ if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
}
@@ -4736,7 +4840,7 @@
// 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) {
- FinishExitWithHardDeoptimization("All known maps handled", join);
+ FinishExitWithHardDeoptimization("Unknown map in polymorphic store",
join);
} else {
HInstruction* instr = BuildStoreNamedGeneric(object, name,
store_value);
instr->set_position(position);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Aug 9
05:50:42 2013
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Aug 9
07:04:47 2013
@@ -3120,47 +3120,6 @@
__ mov(result, FieldOperand(result, offset));
}
}
-
-
-void LCodeGen::EmitLoadFieldOrConstant(Register result,
- Register object,
- Handle<Map> type,
- Handle<String> name,
- LEnvironment* env) {
- LookupResult lookup(isolate());
- type->LookupDescriptor(NULL, *name, &lookup);
- ASSERT(lookup.IsFound() || lookup.IsCacheable());
- if (lookup.IsField()) {
- 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));
- }
- } else if (lookup.IsConstant()) {
- Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
- __ LoadObject(result, constant);
- } else {
- // Negative lookup.
- // Check prototypes.
- Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
- Heap* heap = type->GetHeap();
- while (*current != heap->null_value()) {
- __ LoadHeapObject(result, current);
- __ cmp(FieldOperand(result, HeapObject::kMapOffset),
- Handle<Map>(current->map()));
- DeoptimizeIf(not_equal, env);
- current =
-
Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
- }
- __ mov(result, factory()->undefined_value());
- }
-}
void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
@@ -3179,68 +3138,6 @@
__ push(ToOperand(operand));
}
}
-
-
-// Check for cases where EmitLoadFieldOrConstantFunction needs to walk the
-// prototype chain, which causes unbounded code generation.
-static bool CompactEmit(SmallMapList* list,
- Handle<String> name,
- int i,
- Isolate* isolate) {
- Handle<Map> map = list->at(i);
- LookupResult lookup(isolate);
- map->LookupDescriptor(NULL, *name, &lookup);
- return lookup.IsField() || lookup.IsConstant();
-}
-
-
-void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic*
instr) {
- Register object = ToRegister(instr->object());
- Register result = ToRegister(instr->result());
-
- int map_count = instr->hydrogen()->types()->length();
- bool need_generic = instr->hydrogen()->need_generic();
-
- if (map_count == 0 && !need_generic) {
- DeoptimizeIf(no_condition, instr->environment());
- return;
- }
- Handle<String> name = instr->hydrogen()->name();
- Label done;
- bool all_are_compact = true;
- for (int i = 0; i < map_count; ++i) {
- if (!CompactEmit(instr->hydrogen()->types(), name, i, isolate())) {
- all_are_compact = false;
- break;
- }
- }
- for (int i = 0; i < map_count; ++i) {
- bool last = (i == map_count - 1);
- Handle<Map> map = instr->hydrogen()->types()->at(i);
- Label check_passed;
- __ CompareMap(object, map, &check_passed);
- if (last && !need_generic) {
- DeoptimizeIf(not_equal, instr->environment());
- __ bind(&check_passed);
- EmitLoadFieldOrConstant(result, object, map, name,
instr->environment());
- } else {
- Label next;
- bool compact = all_are_compact ? true :
- CompactEmit(instr->hydrogen()->types(), name, i, isolate());
- __ j(not_equal, &next, compact ? Label::kNear : Label::kFar);
- __ bind(&check_passed);
- EmitLoadFieldOrConstant(result, object, map, name,
instr->environment());
- __ jmp(&done, all_are_compact ? Label::kNear : Label::kFar);
- __ bind(&next);
- }
- }
- if (need_generic) {
- __ mov(ecx, name);
- Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
- CallCode(ic, RelocInfo::CODE_TARGET, instr);
- }
- __ bind(&done);
-}
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Wed Aug 7
19:16:12 2013
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Fri Aug 9
07:04:47 2013
@@ -375,12 +375,6 @@
// Caller should branch on equal condition.
void EmitIsConstructCall(Register temp);
- void EmitLoadFieldOrConstant(Register result,
- Register object,
- Handle<Map> type,
- Handle<String> name,
- LEnvironment* env);
-
// Emits optimized code to deep-copy the contents of statically known
// object graphs (e.g. object literal boilerplate).
void EmitDeepCopy(Handle<JSObject> object,
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Aug 7 19:16:12
2013
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Fri Aug 9 07:04:47
2013
@@ -2203,25 +2203,6 @@
: UseRegisterAtStart(instr->object());
return DefineAsRegister(new(zone()) LLoadNamedField(obj));
}
-
-
-LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
- HLoadNamedFieldPolymorphic* instr) {
- ASSERT(instr->representation().IsTagged());
- if (instr->need_generic()) {
- LOperand* context = UseFixed(instr->context(), esi);
- LOperand* obj = UseFixed(instr->object(), edx);
- LLoadNamedFieldPolymorphic* result =
- new(zone()) LLoadNamedFieldPolymorphic(context, obj);
- return MarkAsCall(DefineFixed(result, eax), instr);
- } else {
- LOperand* context = UseAny(instr->context()); // Not actually used.
- LOperand* obj = UseRegisterAtStart(instr->object());
- LLoadNamedFieldPolymorphic* result =
- new(zone()) LLoadNamedFieldPolymorphic(context, obj);
- return AssignEnvironment(DefineAsRegister(result));
- }
-}
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h Wed Aug 7 19:16:12 2013
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h Fri Aug 9 07:04:47 2013
@@ -127,7 +127,6 @@
V(LoadKeyed) \
V(LoadKeyedGeneric) \
V(LoadNamedField) \
- V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
V(MapEnumLength) \
V(MathAbs) \
@@ -1524,21 +1523,6 @@
};
-class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 2, 0> {
- public:
- LLoadNamedFieldPolymorphic(LOperand* context, LOperand* object) {
- inputs_[0] = context;
- inputs_[1] = object;
- }
-
- LOperand* context() { return inputs_[0]; }
- LOperand* object() { return inputs_[1]; }
-
-
DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic")
- DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic)
-};
-
-
class LLoadNamedGeneric: public LTemplateInstruction<1, 2, 0> {
public:
LLoadNamedGeneric(LOperand* context, LOperand* object) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Fri Aug 9
05:50:42 2013
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Fri Aug 9
07:04:47 2013
@@ -2762,111 +2762,6 @@
__ movq(result, FieldOperand(result, offset));
}
}
-
-
-void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
- Register object,
- Handle<Map> type,
- Handle<String> name,
- LEnvironment* env) {
- LookupResult lookup(isolate());
- type->LookupDescriptor(NULL, *name, &lookup);
- ASSERT(lookup.IsFound() || lookup.IsCacheable());
- if (lookup.IsField()) {
- 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));
- }
- } else if (lookup.IsConstant()) {
- Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
- __ LoadObject(result, constant);
- } else {
- // Negative lookup.
- // Check prototypes.
- Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
- Heap* heap = type->GetHeap();
- while (*current != heap->null_value()) {
- __ LoadHeapObject(result, current);
- __ Cmp(FieldOperand(result, HeapObject::kMapOffset),
- Handle<Map>(current->map()));
- DeoptimizeIf(not_equal, env);
- current =
-
Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
- }
- __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
- }
-}
-
-
-// Check for cases where EmitLoadFieldOrConstantFunction needs to walk the
-// prototype chain, which causes unbounded code generation.
-static bool CompactEmit(SmallMapList* list,
- Handle<String> name,
- int i,
- Isolate* isolate) {
- Handle<Map> map = list->at(i);
- LookupResult lookup(isolate);
- map->LookupDescriptor(NULL, *name, &lookup);
- return lookup.IsField() || lookup.IsConstant();
-}
-
-
-void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic*
instr) {
- Register object = ToRegister(instr->object());
- Register result = ToRegister(instr->result());
-
- int map_count = instr->hydrogen()->types()->length();
- bool need_generic = instr->hydrogen()->need_generic();
-
- if (map_count == 0 && !need_generic) {
- DeoptimizeIf(no_condition, instr->environment());
- return;
- }
- Handle<String> name = instr->hydrogen()->name();
- Label done;
- bool all_are_compact = true;
- for (int i = 0; i < map_count; ++i) {
- if (!CompactEmit(instr->hydrogen()->types(), name, i, isolate())) {
- all_are_compact = false;
- break;
- }
- }
- for (int i = 0; i < map_count; ++i) {
- bool last = (i == map_count - 1);
- Handle<Map> map = instr->hydrogen()->types()->at(i);
- Label check_passed;
- __ CompareMap(object, map, &check_passed);
- if (last && !need_generic) {
- DeoptimizeIf(not_equal, instr->environment());
- __ bind(&check_passed);
- EmitLoadFieldOrConstantFunction(
- result, object, map, name, instr->environment());
- } else {
- Label next;
- bool compact = all_are_compact ? true :
- CompactEmit(instr->hydrogen()->types(), name, i, isolate());
- __ j(not_equal, &next, compact ? Label::kNear : Label::kFar);
- __ bind(&check_passed);
- EmitLoadFieldOrConstantFunction(
- result, object, map, name, instr->environment());
- __ jmp(&done, all_are_compact ? Label::kNear : Label::kFar);
- __ bind(&next);
- }
- }
- if (need_generic) {
- __ Move(rcx, name);
- Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
- CallCode(ic, RelocInfo::CODE_TARGET, instr);
- }
- __ bind(&done);
-}
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.h Wed Aug 7
19:16:12 2013
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.h Fri Aug 9
07:04:47 2013
@@ -324,12 +324,6 @@
// Caller should branch on equal condition.
void EmitIsConstructCall(Register temp);
- void EmitLoadFieldOrConstantFunction(Register result,
- Register object,
- Handle<Map> type,
- Handle<String> name,
- LEnvironment* env);
-
// Emits code for pushing either a tagged constant, a (non-double)
// register, or a stack slot operand.
void EmitPushTaggedOperand(LOperand* operand);
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc Wed Aug 7 19:16:12 2013
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc Fri Aug 9 07:04:47 2013
@@ -2057,23 +2057,6 @@
LOperand* obj = UseRegisterAtStart(instr->object());
return DefineAsRegister(new(zone()) LLoadNamedField(obj));
}
-
-
-LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
- HLoadNamedFieldPolymorphic* instr) {
- ASSERT(instr->representation().IsTagged());
- if (instr->need_generic()) {
- LOperand* obj = UseFixed(instr->object(), rax);
- LLoadNamedFieldPolymorphic* result =
- new(zone()) LLoadNamedFieldPolymorphic(obj);
- return MarkAsCall(DefineFixed(result, rax), instr);
- } else {
- LOperand* obj = UseRegisterAtStart(instr->object());
- LLoadNamedFieldPolymorphic* result =
- new(zone()) LLoadNamedFieldPolymorphic(obj);
- return AssignEnvironment(DefineAsRegister(result));
- }
-}
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h Wed Aug 7 19:16:12 2013
+++ /branches/bleeding_edge/src/x64/lithium-x64.h Fri Aug 9 07:04:47 2013
@@ -126,7 +126,6 @@
V(LoadKeyed) \
V(LoadKeyedGeneric) \
V(LoadNamedField) \
- V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
V(MapEnumLength) \
V(MathAbs) \
@@ -1466,19 +1465,6 @@
};
-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) {
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.