Enable IC stubs for KeyedLaod/Store on ARM.

Several functions are not complete yet, always fall back to slow case.
It fixes test-api/AccessControlIC test.

Review URL: http://codereview.chromium.org/10624

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@745 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
feng@chromium.org 2008-11-13 01:18:31 +00:00
parent 98525aabe3
commit 9d06372cfe
3 changed files with 351 additions and 113 deletions

View File

@ -3239,9 +3239,15 @@ void Reference::GetValue(TypeofState typeof_state) {
// distinction between expressions in a typeof and not in a typeof.
Comment cmnt(masm, "[ Load from keyed Property");
ASSERT(property != NULL);
// TODO(1224671): Implement inline caching for keyed loads as on ia32.
GetPropertyStub stub;
__ CallStub(&stub);
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
Variable* var = expression_->AsVariableProxy()->AsVariable();
if (var != NULL) {
ASSERT(var->is_global());
__ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
} else {
__ Call(ic, RelocInfo::CODE_TARGET);
}
frame->Push(r0);
break;
}
@ -3363,9 +3369,12 @@ void Reference::SetValue(InitState init_state) {
Property* property = expression_->AsProperty();
ASSERT(property != NULL);
__ RecordPosition(property->position());
// Call IC code.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
// TODO(1222589): Make the IC grab the values from the stack.
frame->Pop(r0); // value
SetPropertyStub stub;
__ CallStub(&stub);
__ Call(ic, RelocInfo::CODE_TARGET);
frame->Push(r0);
break;
}

View File

@ -136,24 +136,9 @@ void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
__ ldr(r0, MemOperand(sp, 0));
// Check that the receiver isn't a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
// Check that the object is a JS array.
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
__ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
__ cmp(r1, Operand(JS_ARRAY_TYPE));
__ b(ne, &miss);
// Load length directly from the JS array.
__ ldr(r0, FieldMemOperand(r0, JSArray::kLengthOffset));
__ Ret();
// Cache miss: Jump to runtime.
StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss);
__ bind(&miss);
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
__ Jump(ic, RelocInfo::CODE_TARGET);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
}
@ -185,7 +170,6 @@ void LoadIC::GenerateStringLength(MacroAssembler* masm) {
// -- lr : return address
// -- [sp] : receiver
// -----------------------------------
Label miss, load_length, check_wrapper;
__ ldr(r0, MemOperand(sp, 0));
@ -216,8 +200,7 @@ void LoadIC::GenerateStringLength(MacroAssembler* masm) {
// Cache miss: Jump to runtime.
__ bind(&miss);
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
__ Jump(ic, RelocInfo::CODE_TARGET);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
}
@ -509,33 +492,87 @@ void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
// -- [sp] : receiver
// -----------------------------------
__ ldr(r0, MemOperand(sp, 0));
__ push(r0);
__ push(r2);
__ ldr(r3, MemOperand(sp, 0));
__ stm(db_w, sp, r2.bit() | r3.bit());
// Perform tail call to the entry.
__ TailCallRuntime(f, 2);
}
// TODO(1224671): ICs for keyed load/store is not implemented on ARM.
// TODO(1224671): ICs for keyed load/store is not completed on ARM.
Object* KeyedLoadIC_Miss(Arguments args);
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
}
void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
// ---------- S t a t e --------------
// -- lr : return address
// -- sp[0] : key
// -- sp[4] : receiver
__ ldm(ia, sp, r2.bit() | r3.bit());
__ stm(db_w, sp, r2.bit() | r3.bit());
__ TailCallRuntime(f, 2);
}
// TODO(1224671): implement the fast case.
void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- lr : return address
// -- sp[0] : key
// -- sp[4] : receiver
KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty));
}
void KeyedStoreIC::Generate(MacroAssembler* masm,
const ExternalReference& f) {
// ---------- S t a t e --------------
// -- r0 : value
// -- lr : return address
// -- sp[0] : key
// -- sp[1] : receiver
__ ldm(ia, sp, r2.bit() | r3.bit());
__ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
__ TailCallRuntime(f, 3);
}
// TODO(1224671): implement the fast case.
void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- r0 : value
// -- lr : return address
// -- sp[0] : key
// -- sp[1] : receiver
KeyedStoreIC::Generate(masm, ExternalReference(Runtime::kSetProperty));
}
void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- r0 : value
// -- lr : return address
// -- sp[0] : key
// -- sp[1] : receiver
// ----------- S t a t e -------------
__ ldm(ia, sp, r2.bit() | r3.bit());
__ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
// Perform tail call to the entry.
__ TailCallRuntime(
ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
}

View File

@ -169,6 +169,141 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
}
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 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object,
__ 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 @@ Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
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 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
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 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
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 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
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 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
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,45 +904,126 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
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 __