Index: src/arm/stub-cache-arm.cc |
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc |
index 98d05ac5e91f1f3e6caec67e2e4f508ca758ab6b..03aa359903b418de2e4e831d6856bb4a4f8bd2b7 100644 |
--- a/src/arm/stub-cache-arm.cc |
+++ b/src/arm/stub-cache-arm.cc |
@@ -328,23 +328,24 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
Register src, |
Handle<JSObject> holder, |
PropertyIndex index) { |
- if (index.is_header_index()) { |
- int offset = index.header_index() * kPointerSize; |
- __ ldr(dst, FieldMemOperand(src, offset)); |
- } else { |
- // Adjust for the number of properties stored in the holder. |
- int slot = index.field_index() - holder->map()->inobject_properties(); |
- if (slot < 0) { |
- // Get the property straight out of the holder. |
- int offset = holder->map()->instance_size() + (slot * kPointerSize); |
- __ ldr(dst, FieldMemOperand(src, offset)); |
- } else { |
- // Calculate the offset into the properties array. |
- int offset = slot * kPointerSize + FixedArray::kHeaderSize; |
- __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); |
- __ ldr(dst, FieldMemOperand(dst, offset)); |
- } |
+ DoGenerateFastPropertyLoad( |
+ masm, dst, src, index.is_inobject(holder), index.translate(holder)); |
+} |
+ |
+ |
+void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, |
+ Register dst, |
+ Register src, |
+ bool inobject, |
+ int index) { |
+ int offset = index * kPointerSize; |
+ if (!inobject) { |
+ // Calculate the offset into the properties array. |
+ offset = offset + FixedArray::kHeaderSize; |
+ __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); |
+ src = dst; |
} |
+ __ ldr(dst, FieldMemOperand(src, offset)); |
} |
@@ -1066,6 +1067,11 @@ static void StoreIntAsFloat(MacroAssembler* masm, |
#define __ ACCESS_MASM(masm()) |
+void StubCompiler::GenerateTailCall(Handle<Code> code) { |
+ __ Jump(code, RelocInfo::CODE_TARGET); |
+} |
+ |
+ |
Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
Register object_reg, |
Handle<JSObject> holder, |
@@ -1074,7 +1080,9 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
Register scratch2, |
Handle<String> name, |
int save_at_depth, |
- Label* miss) { |
+ Label* miss, |
+ PrototypeCheckType check) { |
+ Handle<JSObject> first = object; |
// Make sure there's no overlap between holder and object registers. |
ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
@@ -1115,9 +1123,15 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
reg = holder_reg; // From now on the object will be in holder_reg. |
__ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
} else { |
- Handle<Map> current_map(current->map()); |
- __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK, |
- ALLOW_ELEMENT_TRANSITION_MAPS); |
+ Register map_reg = scratch1; |
+ if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { |
+ Handle<Map> current_map(current->map()); |
+ // CheckMap implicitly loads the map of |reg| into |map_reg|. |
+ __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK, |
+ ALLOW_ELEMENT_TRANSITION_MAPS); |
+ } else { |
+ __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
+ } |
// Check access rights to the global object. This has to happen after |
// the map check so that we know that the object is actually a global |
@@ -1130,7 +1144,7 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
if (heap()->InNewSpace(*prototype)) { |
// The prototype is in new space; we cannot store a reference to it |
// in the code. Load it from the map. |
- __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
+ __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
} else { |
// The prototype is in old space; load it directly. |
__ mov(reg, Operand(prototype)); |
@@ -1148,9 +1162,11 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
// Log the check depth. |
LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); |
- // Check the holder map. |
- __ CheckMap(reg, scratch1, Handle<Map>(current->map()), miss, |
- DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
+ if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { |
+ // Check the holder map. |
+ __ CheckMap(reg, scratch1, Handle<Map>(holder->map()), miss, |
+ DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
+ } |
// Perform security check for access to the global object. |
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
@@ -1170,9 +1186,11 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, |
Label* miss) { |
- __ b(success); |
- __ bind(miss); |
- GenerateLoadMiss(masm(), kind()); |
+ if (!miss->is_unused()) { |
+ __ b(success); |
+ __ bind(miss); |
+ GenerateLoadMiss(masm(), kind()); |
+ } |
} |
@@ -1182,12 +1200,10 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
Handle<JSObject> holder, |
Handle<String> name, |
Label* success, |
- FrontendCheckType check, |
Handle<ExecutableAccessorInfo> callback) { |
Label miss; |
- Register reg = HandlerFrontendHeader( |
- object, object_reg, holder, name, &miss, check); |
+ Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
ASSERT(!reg.is(scratch2())); |
@@ -1233,8 +1249,7 @@ void BaseLoadStubCompiler::NonexistentHandlerFrontend( |
Handle<GlobalObject> global) { |
Label miss; |
- Register reg = HandlerFrontendHeader( |
- object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS); |
+ Register reg = HandlerFrontendHeader(object, receiver(), last, name, &miss); |
// If the last object in the prototype chain is a global object, |
// check that the global property cell is empty. |
@@ -2862,7 +2877,7 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent( |
__ Ret(); |
// Return the generated code. |
- return GetCode(Code::NONEXISTENT, factory()->empty_string()); |
+ return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name); |
} |
@@ -2933,8 +2948,10 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
bool is_dont_delete) { |
Label success, miss; |
- HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global), |
- name, &miss, PERFORM_INITIAL_CHECKS); |
+ __ CheckMap( |
+ receiver(), scratch1(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK); |
+ HandlerFrontendHeader( |
+ object, receiver(), Handle<JSObject>::cast(global), name, &miss); |
// Get the value from the cell. |
__ mov(r3, Operand(cell)); |
@@ -2956,7 +2973,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
__ Ret(); |
// Return the generated code. |
- return GetCode(Code::NORMAL, name); |
+ return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name); |
} |
@@ -2984,35 +3001,40 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
__ Jump(ic, RelocInfo::CODE_TARGET); |
// Return the generated code. |
- return GetCode(Code::NORMAL, factory()->empty_string()); |
+ return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string()); |
} |
-Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
+Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( |
MapHandleList* receiver_maps, |
- CodeHandleList* handler_ics) { |
- // ----------- S t a t e ------------- |
- // -- lr : return address |
- // -- r0 : key |
- // -- r1 : receiver |
- // ----------------------------------- |
+ CodeHandleList* handlers, |
+ Handle<String> name, |
+ Code::StubType type, |
+ IcCheckType check) { |
Label miss; |
- __ JumpIfSmi(r1, &miss); |
+ |
+ if (check == PROPERTY) { |
+ GenerateNameCheck(name, this->name(), &miss); |
+ } |
+ |
+ __ JumpIfSmi(receiver(), &miss); |
+ Register map_reg = scratch1(); |
int receiver_count = receiver_maps->length(); |
- __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
+ __ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
for (int current = 0; current < receiver_count; ++current) { |
__ mov(ip, Operand(receiver_maps->at(current))); |
- __ cmp(r2, ip); |
- __ Jump(handler_ics->at(current), RelocInfo::CODE_TARGET, eq); |
+ __ cmp(map_reg, ip); |
+ __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq); |
} |
__ bind(&miss); |
- Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
- __ Jump(miss_ic, RelocInfo::CODE_TARGET, al); |
+ GenerateLoadMiss(masm(), kind()); |
// Return the generated code. |
- return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
+ InlineCacheState state = |
+ receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; |
+ return GetCode(Code::IC_FRAGMENT, type, name, state); |
} |