Index: src/mips/lithium-codegen-mips.cc |
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc |
index 2073d04d9e924e7400e3987ae78f37b9043b1295..a7df7fee90fab638d189885b7bb8d24e0d63e177 100644 |
--- a/src/mips/lithium-codegen-mips.cc |
+++ b/src/mips/lithium-codegen-mips.cc |
@@ -2315,12 +2315,12 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, |
Register object, |
Handle<Map> type, |
- Handle<String> name) { |
+ Handle<String> name, |
+ LEnvironment* env) { |
LookupResult lookup(isolate()); |
type->LookupInDescriptors(NULL, *name, &lookup); |
- ASSERT(lookup.IsFound() && |
- (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); |
- if (lookup.type() == FIELD) { |
+ ASSERT(lookup.IsFound() || lookup.IsCacheable()); |
+ if (lookup.IsFound() && lookup.type() == FIELD) { |
int index = lookup.GetLocalFieldIndexFromMap(*type); |
int offset = index * kPointerSize; |
if (index < 0) { |
@@ -2332,9 +2332,23 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, |
__ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
__ lw(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize)); |
} |
- } else { |
+ } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) { |
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type)); |
__ LoadHeapObject(result, function); |
+ } else { |
+ // Negative lookup. |
+ // Check prototypes. |
+ HeapObject* current = HeapObject::cast((*type)->prototype()); |
+ Heap* heap = type->GetHeap(); |
+ while (current != heap->null_value()) { |
+ Handle<HeapObject> link(current); |
+ __ LoadHeapObject(result, link); |
+ __ lw(result, FieldMemOperand(result, HeapObject::kMapOffset)); |
+ DeoptimizeIf(ne, env, |
+ result, Operand(Handle<Map>(JSObject::cast(current)->map()))); |
+ current = HeapObject::cast(current->map()->prototype()); |
+ } |
+ __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
} |
} |
@@ -2342,7 +2356,7 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, |
void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { |
Register object = ToRegister(instr->object()); |
Register result = ToRegister(instr->result()); |
- Register scratch = scratch0(); |
+ Register object_map = scratch0(); |
int map_count = instr->hydrogen()->types()->length(); |
bool need_generic = instr->hydrogen()->need_generic(); |
@@ -2353,17 +2367,25 @@ void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { |
} |
Handle<String> name = instr->hydrogen()->name(); |
Label done; |
- __ lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
+ __ lw(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; |
+ __ CompareMapAndBranch( |
+ object_map, map, &check_passed, |
+ eq, &check_passed, ALLOW_ELEMENT_TRANSITION_MAPS); |
if (last && !need_generic) { |
- DeoptimizeIf(ne, instr->environment(), scratch, Operand(map)); |
- EmitLoadFieldOrConstantFunction(result, object, map, name); |
+ DeoptimizeIf(al, instr->environment()); |
+ __ bind(&check_passed); |
+ EmitLoadFieldOrConstantFunction( |
+ result, object, map, name, instr->environment()); |
} else { |
Label next; |
- __ Branch(&next, ne, scratch, Operand(map)); |
- EmitLoadFieldOrConstantFunction(result, object, map, name); |
+ __ Branch(&next); |
+ __ bind(&check_passed); |
+ EmitLoadFieldOrConstantFunction( |
+ result, object, map, name, instr->environment()); |
__ Branch(&done); |
__ bind(&next); |
} |