From 89176e88d80eb091f6b5b4a0c23f081376a06aaa Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Wed, 13 Jun 2012 11:09:28 +0000 Subject: [PATCH] MIPS: Add negative lookups to polymorphic loads in Crankshaft. This is a commit of https://chromiumcodereview.appspot.com/10536130/ for Akos Palfi. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11794 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/lithium-codegen-mips.cc | 44 ++++++++++++++++++++++++++++++---------- src/mips/lithium-codegen-mips.h | 3 ++- src/mips/macro-assembler-mips.cc | 14 +++++++++++-- src/mips/macro-assembler-mips.h | 9 ++++++++ 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 932f6aa..67dbe69 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 type, - Handle name) { + Handle 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 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 link(current); + __ LoadHeapObject(result, link); + __ lw(result, FieldMemOperand(result, HeapObject::kMapOffset)); + DeoptimizeIf(ne, env, + result, Operand(Handle(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 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 = 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); } diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h index 61a15a3..32a696b 100644 --- a/src/mips/lithium-codegen-mips.h +++ b/src/mips/lithium-codegen-mips.h @@ -334,7 +334,8 @@ class LCodeGen BASE_EMBEDDED { void EmitLoadFieldOrConstantFunction(Register result, Register object, Handle type, - Handle name); + Handle name, + LEnvironment* env); // Emits optimized code to deep-copy the contents of statically known // object graphs (e.g. object literal boilerplate). diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index 14b7308..51b3a38 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -3473,6 +3473,16 @@ void MacroAssembler::CompareMapAndBranch(Register obj, Label* branch_to, CompareMapMode mode) { lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); + CompareMapAndBranch(scratch, map, early_success, cond, branch_to, mode); +} + + +void MacroAssembler::CompareMapAndBranch(Register obj_map, + Handle map, + Label* early_success, + Condition cond, + Label* branch_to, + CompareMapMode mode) { Operand right = Operand(map); if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) { ElementsKind kind = map->elements_kind(); @@ -3483,13 +3493,13 @@ void MacroAssembler::CompareMapAndBranch(Register obj, kind = GetNextMoreGeneralFastElementsKind(kind, packed); current_map = current_map->LookupElementsTransitionMap(kind); if (!current_map) break; - Branch(early_success, eq, scratch, right); + Branch(early_success, eq, obj_map, right); right = Operand(Handle(current_map)); } } } - Branch(branch_to, cond, scratch, right); + Branch(branch_to, cond, obj_map, right); } diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index 1766866..bb3dc01 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -992,6 +992,15 @@ class MacroAssembler: public Assembler { Label* branch_to, CompareMapMode mode = REQUIRE_EXACT_MAP); + // As above, but the map of the object is already loaded into the register + // which is preserved by the code generated. + void CompareMapAndBranch(Register obj_map, + Handle map, + Label* early_success, + Condition cond, + Label* branch_to, + CompareMapMode mode = REQUIRE_EXACT_MAP); + // Check if the map of an object is equal to a specified map and branch to // label if not. Skip the smi check if not required (object is known to be a // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match -- 2.7.4