| Index: src/stub-cache-arm.cc
|
| ===================================================================
|
| --- src/stub-cache-arm.cc (revision 727)
|
| +++ src/stub-cache-arm.cc (working copy)
|
| @@ -169,6 +169,141 @@
|
| }
|
|
|
|
|
| +void StubCompiler::GenerateLoadField(MacroAssembler* masm,
|
| + JSObject* object,
|
| + JSObject* holder,
|
| + Register receiver,
|
| + Register scratch1,
|
| + Register scratch2,
|
| + int index,
|
| + Label* miss_label) {
|
| + // Check that the receiver isn't a smi.
|
| + __ tst(receiver, Operand(kSmiTagMask));
|
| + __ b(eq, miss_label);
|
| +
|
| + // Check that the maps haven't changed.
|
| + Register reg =
|
| + __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
|
| + GenerateFastPropertyLoad(masm, r0, reg, holder, index);
|
| + __ Ret();
|
| +}
|
| +
|
| +
|
| +void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
|
| + JSObject* object,
|
| + JSObject* holder,
|
| + Register receiver,
|
| + Register scratch1,
|
| + Register scratch2,
|
| + Object* value,
|
| + Label* miss_label) {
|
| + // Check that the receiver isn't a smi.
|
| + __ tst(receiver, Operand(kSmiTagMask));
|
| + __ b(eq, miss_label);
|
| +
|
| + // Check that the maps haven't changed.
|
| + Register reg =
|
| + __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
|
| +
|
| + // Return the constant value.
|
| + __ mov(r0, Operand(Handle<Object>(value)));
|
| + __ Ret();
|
| +}
|
| +
|
| +
|
| +void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
|
| + JSObject* object,
|
| + JSObject* holder,
|
| + Register receiver,
|
| + Register name,
|
| + Register scratch1,
|
| + Register scratch2,
|
| + AccessorInfo* callback,
|
| + Label* miss_label) {
|
| + // Check that the receiver isn't a smi.
|
| + __ tst(receiver, Operand(kSmiTagMask));
|
| + __ b(eq, miss_label);
|
| +
|
| + // Check that the maps haven't changed.
|
| + Register reg =
|
| + __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
|
| +
|
| + // Push the arguments on the JS stack of the caller.
|
| + __ push(receiver); // receiver
|
| + __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
|
| + __ push(ip);
|
| + __ push(name); // name
|
| + __ push(reg); // holder
|
| +
|
| + // Do tail-call to the runtime system.
|
| + ExternalReference load_callback_property =
|
| + ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
|
| + __ TailCallRuntime(load_callback_property, 4);
|
| +}
|
| +
|
| +
|
| +void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
|
| + JSObject* object,
|
| + JSObject* holder,
|
| + Register receiver,
|
| + Register name,
|
| + Register scratch1,
|
| + Register scratch2,
|
| + Label* miss_label) {
|
| + // Check that the receiver isn't a smi.
|
| + __ tst(receiver, Operand(kSmiTagMask));
|
| + __ b(eq, miss_label);
|
| +
|
| + // Check that the maps haven't changed.
|
| + Register reg =
|
| + __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
|
| +
|
| + // Push the arguments on the JS stack of the caller.
|
| + __ push(receiver); // receiver
|
| + __ push(reg); // holder
|
| + __ push(name); // name
|
| +
|
| + // Do tail-call to the runtime system.
|
| + ExternalReference load_ic_property =
|
| + ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
|
| + __ TailCallRuntime(load_ic_property, 3);
|
| +}
|
| +
|
| +
|
| +void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
|
| + Register receiver,
|
| + Register scratch,
|
| + Label* miss_label) {
|
| + // Check that the receiver isn't a smi.
|
| + __ tst(receiver, Operand(kSmiTagMask));
|
| + __ b(eq, miss_label);
|
| +
|
| + // Check that the object is a JS array.
|
| + __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| + __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
|
| + __ cmp(scratch, Operand(JS_ARRAY_TYPE));
|
| + __ b(ne, miss_label);
|
| +
|
| + // Load length directly from the JS array.
|
| + __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
| + __ Ret();
|
| +}
|
| +
|
| +
|
| +void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
|
| + ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
|
| + Code* code = NULL;
|
| + if (kind == Code::LOAD_IC) {
|
| + code = Builtins::builtin(Builtins::LoadIC_Miss);
|
| + } else {
|
| + code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
|
| + }
|
| +
|
| + Handle<Code> ic(code);
|
| + __ Jump(ic, RelocInfo::CODE_TARGET);
|
| +}
|
| +
|
| +
|
| #undef __
|
|
|
| #define __ masm()->
|
| @@ -633,20 +768,9 @@
|
|
|
| __ ldr(r0, MemOperand(sp, 0));
|
|
|
| - // Check that the receiver isn't a smi.
|
| - __ tst(r0, Operand(kSmiTagMask));
|
| - __ b(eq, &miss);
|
| -
|
| - // Check that the maps haven't changed.
|
| - Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
|
| - GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
|
| - __ Ret();
|
| -
|
| - // Handle load cache miss.
|
| + GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
|
| __ bind(&miss);
|
| - __ ldr(r0, MemOperand(sp)); // restore receiver
|
| - Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
|
| - __ Jump(ic, RelocInfo::CODE_TARGET);
|
| + GenerateLoadMiss(masm(), Code::LOAD_IC);
|
|
|
| // Return the generated code.
|
| return GetCode(FIELD);
|
| @@ -666,29 +790,9 @@
|
| Label miss;
|
|
|
| __ ldr(r0, MemOperand(sp, 0));
|
| - // Check that the receiver isn't a smi.
|
| - __ tst(r0, Operand(kSmiTagMask));
|
| - __ b(eq, &miss);
|
| -
|
| - // Check that the maps haven't changed.
|
| - Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
|
| -
|
| - // Push the arguments on the JS stack of the caller.
|
| - __ push(r0); // receiver
|
| - __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
|
| - __ push(ip);
|
| - __ push(r2); // name
|
| - __ push(reg); // holder
|
| -
|
| - // Do tail-call to the runtime system.
|
| - ExternalReference load_callback_property =
|
| - ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
|
| - __ TailCallRuntime(load_callback_property, 4);
|
| -
|
| - // Handle load cache miss.
|
| + GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback, &miss);
|
| __ bind(&miss);
|
| - Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
|
| - __ Jump(ic, RelocInfo::CODE_TARGET);
|
| + GenerateLoadMiss(masm(), Code::LOAD_IC);
|
|
|
| // Return the generated code.
|
| return GetCode(CALLBACKS);
|
| @@ -708,21 +812,10 @@
|
| Label miss;
|
|
|
| __ ldr(r0, MemOperand(sp, 0));
|
| - // Check that the receiver isn't a smi.
|
| - __ tst(r0, Operand(kSmiTagMask));
|
| - __ b(eq, &miss);
|
|
|
| - // Check that the maps haven't changed.
|
| - Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
|
| -
|
| - // Return the constant value.
|
| - __ mov(r0, Operand(Handle<Object>(value)));
|
| - __ Ret();
|
| -
|
| - // Handle load cache miss.
|
| + GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
|
| __ bind(&miss);
|
| - Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
|
| - __ Jump(ic, RelocInfo::CODE_TARGET);
|
| + GenerateLoadMiss(masm(), Code::LOAD_IC);
|
|
|
| // Return the generated code.
|
| return GetCode(CONSTANT_FUNCTION);
|
| @@ -742,27 +835,10 @@
|
| Label miss;
|
|
|
| __ ldr(r0, MemOperand(sp, 0));
|
| - // Check that the receiver isn't a smi.
|
| - __ tst(r0, Operand(kSmiTagMask));
|
| - __ b(eq, &miss);
|
|
|
| - // Check that the maps haven't changed.
|
| - Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
|
| -
|
| - // Push the arguments on the JS stack of the caller.
|
| - __ push(r0); // receiver
|
| - __ push(reg); // holder
|
| - __ push(r2); // name
|
| -
|
| - // Do tail-call to the runtime system.
|
| - ExternalReference load_ic_property =
|
| - ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
|
| - __ TailCallRuntime(load_ic_property, 3);
|
| -
|
| - // Handle load cache miss.
|
| + GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
|
| __ bind(&miss);
|
| - Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
|
| - __ Jump(ic, RelocInfo::CODE_TARGET);
|
| + GenerateLoadMiss(masm(), Code::LOAD_IC);
|
|
|
| // Return the generated code.
|
| return GetCode(INTERCEPTOR);
|
| @@ -775,8 +851,25 @@
|
| JSObject* receiver,
|
| JSObject* holder,
|
| int index) {
|
| - UNIMPLEMENTED();
|
| - return Heap::undefined_value();
|
| + // ----------- S t a t e -------------
|
| + // -- lr : return address
|
| + // -- sp[0] : key
|
| + // -- sp[4] : receiver
|
| + // -----------------------------------
|
| + HandleScope scope;
|
| + Label miss;
|
| +
|
| + __ ldr(r2, MemOperand(sp, 0));
|
| + __ ldr(r0, MemOperand(sp, kPointerSize));
|
| +
|
| + __ cmp(r2, Operand(Handle<String>(name)));
|
| + __ b(ne, &miss);
|
| +
|
| + GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
|
| + __ bind(&miss);
|
| + GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
| +
|
| + return GetCode(FIELD);
|
| }
|
|
|
|
|
| @@ -784,8 +877,26 @@
|
| JSObject* receiver,
|
| JSObject* holder,
|
| AccessorInfo* callback) {
|
| - UNIMPLEMENTED();
|
| - return Heap::undefined_value();
|
| + // ----------- S t a t e -------------
|
| + // -- lr : return address
|
| + // -- sp[0] : key
|
| + // -- sp[4] : receiver
|
| + // -----------------------------------
|
| + HandleScope scope;
|
| + Label miss;
|
| +
|
| + __ ldr(r2, MemOperand(sp, 0));
|
| + __ ldr(r0, MemOperand(sp, kPointerSize));
|
| +
|
| + __ cmp(r2, Operand(Handle<String>(name)));
|
| + __ b(ne, &miss);
|
| +
|
| + GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
|
| + r1, callback, &miss);
|
| + __ bind(&miss);
|
| + GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
| +
|
| + return GetCode(CALLBACKS);
|
| }
|
|
|
|
|
| @@ -793,47 +904,128 @@
|
| JSObject* receiver,
|
| JSObject* holder,
|
| Object* value) {
|
| - UNIMPLEMENTED();
|
| - return Heap::undefined_value();
|
| + // ----------- S t a t e -------------
|
| + // -- lr : return address
|
| + // -- sp[0] : key
|
| + // -- sp[4] : receiver
|
| + // -----------------------------------
|
| + HandleScope scope;
|
| + Label miss;
|
| +
|
| + // Check the key is the cached one
|
| + __ ldr(r2, MemOperand(sp, 0));
|
| + __ ldr(r0, MemOperand(sp, kPointerSize));
|
| +
|
| + __ cmp(r2, Operand(Handle<String>(name)));
|
| + __ b(ne, &miss);
|
| +
|
| + GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
|
| + __ bind(&miss);
|
| + GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
| +
|
| + // Return the generated code.
|
| + return GetCode(CONSTANT_FUNCTION);
|
| }
|
|
|
|
|
| Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
|
| JSObject* holder,
|
| String* name) {
|
| - UNIMPLEMENTED();
|
| - return Heap::undefined_value();
|
| + // ----------- S t a t e -------------
|
| + // -- lr : return address
|
| + // -- sp[0] : key
|
| + // -- sp[4] : receiver
|
| + // -----------------------------------
|
| + HandleScope scope;
|
| + Label miss;
|
| +
|
| + // Check the key is the cached one
|
| + __ ldr(r2, MemOperand(sp, 0));
|
| + __ ldr(r0, MemOperand(sp, kPointerSize));
|
| +
|
| + __ cmp(r2, Operand(Handle<String>(name)));
|
| + __ b(ne, &miss);
|
| +
|
| + GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
|
| + __ bind(&miss);
|
| + GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
| +
|
| + return GetCode(INTERCEPTOR);
|
| }
|
|
|
|
|
| Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
|
| - UNIMPLEMENTED();
|
| - return Heap::undefined_value();
|
| + // ----------- S t a t e -------------
|
| + // -- lr : return address
|
| + // -- sp[0] : key
|
| + // -- sp[4] : receiver
|
| + // -----------------------------------
|
| + HandleScope scope;
|
| + Label miss;
|
| +
|
| + // Check the key is the cached one
|
| + __ ldr(r2, MemOperand(sp, 0));
|
| + __ ldr(r0, MemOperand(sp, kPointerSize));
|
| +
|
| + __ cmp(r2, Operand(Handle<String>(name)));
|
| + __ b(ne, &miss);
|
| +
|
| + GenerateLoadArrayLength(masm(), r0, r3, &miss);
|
| + __ bind(&miss);
|
| + GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
| +
|
| + return GetCode(CALLBACKS);
|
| }
|
|
|
|
|
| +// TODO(1224671): implement the fast case.
|
| Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
|
| - UNIMPLEMENTED();
|
| - return Heap::undefined_value();
|
| + // ----------- S t a t e -------------
|
| + // -- lr : return address
|
| + // -- sp[0] : key
|
| + // -- sp[4] : receiver
|
| + // -----------------------------------
|
| + HandleScope scope;
|
| + GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
| +
|
| + return GetCode(CALLBACKS);
|
| }
|
|
|
|
|
| +// TODO(1224671): implement the fast case.
|
| Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
|
| - UNIMPLEMENTED();
|
| - return Heap::undefined_value();
|
| + // ----------- S t a t e -------------
|
| + // -- lr : return address
|
| + // -- sp[0] : key
|
| + // -- sp[4] : receiver
|
| + // -----------------------------------
|
| + HandleScope scope;
|
| + GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
| +
|
| + return GetCode(CALLBACKS);
|
| }
|
|
|
|
|
| +// TODO(1224671): implement the fast case.
|
| Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
|
| int index,
|
| Map* transition,
|
| String* name) {
|
| - UNIMPLEMENTED();
|
| - return Heap::undefined_value();
|
| + // ----------- S t a t e -------------
|
| + // -- r0 : value
|
| + // -- r2 : name
|
| + // -- lr : return address
|
| + // -- [sp] : receiver
|
| + // -----------------------------------
|
| + HandleScope scope;
|
| + Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
|
| + __ Jump(ic, RelocInfo::CODE_TARGET);
|
| +
|
| + // Return the generated code.
|
| + return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
|
| }
|
|
|
|
|
| -
|
| #undef __
|
|
|
| } } // namespace v8::internal
|
|
|