Commit 095ce23d authored by verwaest@chromium.org's avatar verwaest@chromium.org

Remove BaseLoad/StoreStub compilers, and the stub-cache interface duplication.

R=ulan@chromium.org

Review URL: https://chromiumcodereview.appspot.com/26873002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17165 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f878c1c3
......@@ -433,7 +433,7 @@ static void GenerateCheckPropertyCell(MacroAssembler* masm,
}
void BaseStoreStubCompiler::GenerateNegativeHolderLookup(
void StoreStubCompiler::GenerateNegativeHolderLookup(
MacroAssembler* masm,
Handle<JSObject> holder,
Register holder_reg,
......@@ -453,19 +453,19 @@ void BaseStoreStubCompiler::GenerateNegativeHolderLookup(
// When leaving generated code after success, the receiver_reg and name_reg
// may be clobbered. Upon branch to miss_label, the receiver and name
// registers have their original values.
void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
Register receiver_reg,
Register storage_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Register scratch3,
Label* miss_label,
Label* slow) {
void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
Register receiver_reg,
Register storage_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Register scratch3,
Label* miss_label,
Label* slow) {
// r0 : value
Label exit;
......@@ -617,15 +617,15 @@ void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
// When leaving generated code after success, the receiver_reg and name_reg
// may be clobbered. Upon branch to miss_label, the receiver and name
// registers have their original values.
void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Register receiver_reg,
Register name_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Label* miss_label) {
void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Register receiver_reg,
Register name_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Label* miss_label) {
// r0 : value
Label exit;
......@@ -736,9 +736,9 @@ void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
}
void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
Label* label,
Handle<Name> name) {
void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
Label* label,
Handle<Name> name) {
if (!label->is_unused()) {
__ bind(label);
__ mov(this->name(), Operand(name));
......@@ -1304,9 +1304,9 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
}
void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
if (!miss->is_unused()) {
__ b(success);
__ bind(miss);
......@@ -1315,9 +1315,9 @@ void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
}
void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
if (!miss->is_unused()) {
__ b(success);
GenerateRestoreName(masm(), miss, name);
......@@ -1326,7 +1326,7 @@ void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
}
Register BaseLoadStubCompiler::CallbackHandlerFrontend(
Register LoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
......@@ -1373,7 +1373,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend(
}
void BaseLoadStubCompiler::NonexistentHandlerFrontend(
void LoadStubCompiler::NonexistentHandlerFrontend(
Handle<JSObject> object,
Handle<JSObject> last,
Handle<Name> name,
......@@ -1393,10 +1393,10 @@ void BaseLoadStubCompiler::NonexistentHandlerFrontend(
}
void BaseLoadStubCompiler::GenerateLoadField(Register reg,
Handle<JSObject> holder,
PropertyIndex field,
Representation representation) {
void LoadStubCompiler::GenerateLoadField(Register reg,
Handle<JSObject> holder,
PropertyIndex field,
Representation representation) {
if (!reg.is(receiver())) __ mov(receiver(), reg);
if (kind() == Code::LOAD_IC) {
LoadFieldStub stub(field.is_inobject(holder),
......@@ -1412,21 +1412,21 @@ void BaseLoadStubCompiler::GenerateLoadField(Register reg,
}
void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
// Return the constant value.
__ LoadObject(r0, value);
__ Ret();
}
void BaseLoadStubCompiler::GenerateLoadCallback(
void LoadStubCompiler::GenerateLoadCallback(
const CallOptimization& call_optimization) {
GenerateFastApiCall(
masm(), call_optimization, receiver(), scratch3(), 0, NULL);
}
void BaseLoadStubCompiler::GenerateLoadCallback(
void LoadStubCompiler::GenerateLoadCallback(
Register reg,
Handle<ExecutableAccessorInfo> callback) {
// Build AccessorInfo::args_ list on the stack and push property name below
......@@ -1492,7 +1492,7 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
}
void BaseLoadStubCompiler::GenerateLoadInterceptor(
void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg,
Handle<JSObject> object,
Handle<JSObject> interceptor_holder,
......@@ -3004,6 +3004,7 @@ void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
Register receiver,
Handle<JSFunction> getter) {
// ----------- S t a t e -------------
// -- r0 : receiver
......@@ -3015,7 +3016,7 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
if (!getter.is_null()) {
// Call the JavaScript getter with the receiver on the stack.
__ push(r0);
__ push(receiver);
ParameterCount actual(0);
ParameterCount expected(getter);
__ InvokeFunction(getter, expected, actual,
......
......@@ -1319,7 +1319,8 @@ static void Generate_LoadIC_Normal(MacroAssembler* masm) {
static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
LoadStubCompiler::GenerateLoadViaGetter(masm, Handle<JSFunction>());
LoadStubCompiler::GenerateLoadViaGetter(
masm, LoadStubCompiler::registers()[0], Handle<JSFunction>());
}
......
......@@ -779,9 +779,9 @@ class CallInterceptorCompiler BASE_EMBEDDED {
};
void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
Label* label,
Handle<Name> name) {
void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
Label* label,
Handle<Name> name) {
if (!label->is_unused()) {
__ bind(label);
__ mov(this->name(), Immediate(name));
......@@ -812,7 +812,7 @@ static void GenerateCheckPropertyCell(MacroAssembler* masm,
}
void BaseStoreStubCompiler::GenerateNegativeHolderLookup(
void StoreStubCompiler::GenerateNegativeHolderLookup(
MacroAssembler* masm,
Handle<JSObject> holder,
Register holder_reg,
......@@ -830,19 +830,19 @@ void BaseStoreStubCompiler::GenerateNegativeHolderLookup(
// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
// store is successful.
void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
Register receiver_reg,
Register storage_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Register unused,
Label* miss_label,
Label* slow) {
void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
Register receiver_reg,
Register storage_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Register unused,
Label* miss_label,
Label* slow) {
int descriptor = transition->LastAdded();
DescriptorArray* descriptors = transition->instance_descriptors();
PropertyDetails details = descriptors->GetDetails(descriptor);
......@@ -1001,15 +1001,15 @@ void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
// Both name_reg and receiver_reg are preserved on jumps to miss_label,
// but may be destroyed if store is successful.
void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Register receiver_reg,
Register name_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Label* miss_label) {
void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Register receiver_reg,
Register name_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Label* miss_label) {
// Stub never generated for non-global objects that require access
// checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
......@@ -1273,9 +1273,9 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
}
void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
if (!miss->is_unused()) {
__ jmp(success);
__ bind(miss);
......@@ -1284,9 +1284,9 @@ void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
}
void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
if (!miss->is_unused()) {
__ jmp(success);
GenerateRestoreName(masm(), miss, name);
......@@ -1295,7 +1295,7 @@ void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
}
Register BaseLoadStubCompiler::CallbackHandlerFrontend(
Register LoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
......@@ -1355,7 +1355,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend(
}
void BaseLoadStubCompiler::NonexistentHandlerFrontend(
void LoadStubCompiler::NonexistentHandlerFrontend(
Handle<JSObject> object,
Handle<JSObject> last,
Handle<Name> name,
......@@ -1375,10 +1375,10 @@ void BaseLoadStubCompiler::NonexistentHandlerFrontend(
}
void BaseLoadStubCompiler::GenerateLoadField(Register reg,
Handle<JSObject> holder,
PropertyIndex field,
Representation representation) {
void LoadStubCompiler::GenerateLoadField(Register reg,
Handle<JSObject> holder,
PropertyIndex field,
Representation representation) {
if (!reg.is(receiver())) __ mov(receiver(), reg);
if (kind() == Code::LOAD_IC) {
LoadFieldStub stub(field.is_inobject(holder),
......@@ -1394,14 +1394,14 @@ void BaseLoadStubCompiler::GenerateLoadField(Register reg,
}
void BaseLoadStubCompiler::GenerateLoadCallback(
void LoadStubCompiler::GenerateLoadCallback(
const CallOptimization& call_optimization) {
GenerateFastApiCall(
masm(), call_optimization, receiver(), scratch3(), 0, NULL);
}
void BaseLoadStubCompiler::GenerateLoadCallback(
void LoadStubCompiler::GenerateLoadCallback(
Register reg,
Handle<ExecutableAccessorInfo> callback) {
// Insert additional parameters into the stack frame above return address.
......@@ -1467,14 +1467,14 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
}
void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
// Return the constant value.
__ LoadObject(eax, value);
__ ret(0);
}
void BaseLoadStubCompiler::GenerateLoadInterceptor(
void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg,
Handle<JSObject> object,
Handle<JSObject> interceptor_holder,
......@@ -3114,18 +3114,14 @@ void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
Register receiver,
Handle<JSFunction> getter) {
// ----------- S t a t e -------------
// -- ecx : name
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
{
FrameScope scope(masm, StackFrame::INTERNAL);
if (!getter.is_null()) {
// Call the JavaScript getter with the receiver on the stack.
__ push(edx);
__ push(receiver);
ParameterCount actual(0);
ParameterCount expected(getter);
__ InvokeFunction(getter, expected, actual,
......
......@@ -1105,6 +1105,18 @@ void IC::PatchCache(Handle<HeapObject> receiver,
}
Handle<Code> LoadIC::SimpleFieldLoad(int offset,
bool inobject,
Representation representation) {
if (kind() == Code::LOAD_IC) {
LoadFieldStub stub(inobject, offset, representation);
return stub.GetCode(isolate());
} else {
KeyedLoadFieldStub stub(inobject, offset, representation);
return stub.GetCode(isolate());
}
}
void LoadIC::UpdateCaches(LookupResult* lookup,
Handle<Object> object,
Handle<String> name) {
......@@ -1126,13 +1138,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
} else if (object->IsString() &&
name->Equals(isolate()->heap()->length_string())) {
int length_index = String::kLengthOffset / kPointerSize;
if (target()->is_load_stub()) {
LoadFieldStub stub(true, length_index, Representation::Tagged());
code = stub.GetCode(isolate());
} else {
KeyedLoadFieldStub stub(true, length_index, Representation::Tagged());
code = stub.GetCode(isolate());
}
code = SimpleFieldLoad(length_index);
} else if (!object->IsJSObject()) {
// TODO(jkummerow): It would be nice to support non-JSObjects in
// ComputeLoadHandler, then we wouldn't need to go generic here.
......@@ -1167,7 +1173,6 @@ Handle<Code> IC::ComputeHandler(LookupResult* lookup,
if (!code.is_null()) return code;
code = CompileHandler(lookup, receiver, name, value);
if (code.is_null()) return slow_stub();
if (code->is_handler() && code->type() != Code::NORMAL) {
HeapObject::UpdateMapCodeCache(receiver, name, code);
......@@ -1182,24 +1187,33 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
Handle<String> name,
Handle<Object> unused) {
Handle<JSObject> holder(lookup->holder());
LoadStubCompiler compiler(isolate(), kind());
switch (lookup->type()) {
case FIELD:
return isolate()->stub_cache()->ComputeLoadField(
name, receiver, holder,
lookup->GetFieldIndex(), lookup->representation());
case FIELD: {
PropertyIndex field = lookup->GetFieldIndex();
if (receiver.is_identical_to(holder)) {
return SimpleFieldLoad(field.translate(holder),
field.is_inobject(holder),
lookup->representation());
}
return compiler.CompileLoadField(
receiver, holder, name, field, lookup->representation());
}
case CONSTANT: {
Handle<Object> constant(lookup->GetConstant(), isolate());
// TODO(2803): Don't compute a stub for cons strings because they cannot
// be embedded into code.
if (constant->IsConsString()) return Handle<Code>::null();
return isolate()->stub_cache()->ComputeLoadConstant(
name, receiver, holder, constant);
if (constant->IsConsString()) break;
return compiler.CompileLoadConstant(receiver, holder, name, constant);
}
case NORMAL:
if (kind() != Code::LOAD_IC) break;
if (holder->IsGlobalObject()) {
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
Handle<PropertyCell> cell(
global->GetPropertyCell(lookup), isolate());
// TODO(verwaest): Turn into a handler.
return isolate()->stub_cache()->ComputeLoadGlobal(
name, receiver, global, cell, lookup->IsDontDelete());
}
......@@ -1208,18 +1222,16 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
// property must be found in the receiver for the stub to be
// applicable.
if (!holder.is_identical_to(receiver)) break;
return isolate()->stub_cache()->ComputeLoadNormal(name, receiver);
return isolate()->builtins()->LoadIC_Normal();
case CALLBACKS: {
{
// Use simple field loads for some well-known callback properties.
int object_offset;
Handle<Map> map(receiver->map());
if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
PropertyIndex index =
PropertyIndex::NewHeaderIndex(object_offset / kPointerSize);
return isolate()->stub_cache()->ComputeLoadField(
name, receiver, receiver, index, Representation::Tagged());
}
// Use simple field loads for some well-known callback properties.
int object_offset;
Handle<Map> map(receiver->map());
if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
PropertyIndex index =
PropertyIndex::NewHeaderIndex(object_offset / kPointerSize);
return compiler.CompileLoadField(
receiver, receiver, name, index, Representation::Tagged());
}
Handle<Object> callback(lookup->GetCallbackObject(), isolate());
......@@ -1228,8 +1240,7 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
Handle<ExecutableAccessorInfo>::cast(callback);
if (v8::ToCData<Address>(info->getter()) == 0) break;
if (!info->IsCompatibleReceiver(*receiver)) break;
return isolate()->stub_cache()->ComputeLoadCallback(
name, receiver, holder, info);
return compiler.CompileLoadCallback(receiver, holder, name, info);
} else if (callback->IsAccessorPair()) {
Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
isolate());
......@@ -1240,11 +1251,10 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() &&
call_optimization.IsCompatibleReceiver(*receiver)) {
return isolate()->stub_cache()->ComputeLoadCallback(
name, receiver, holder, call_optimization);
return compiler.CompileLoadCallback(
receiver, holder, name, call_optimization);
}
return isolate()->stub_cache()->ComputeLoadViaGetter(
name, receiver, holder, function);
return compiler.CompileLoadViaGetter(receiver, holder, name, function);
}
// TODO(dcarney): Handle correctly.
if (callback->IsDeclaredAccessorInfo()) break;
......@@ -1254,12 +1264,12 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
}
case INTERCEPTOR:
ASSERT(HasInterceptorGetter(*holder));
return isolate()->stub_cache()->ComputeLoadInterceptor(
name, receiver, holder);
return compiler.CompileLoadInterceptor(receiver, holder, name);
default:
break;
}
return Handle<Code>::null();
return slow_stub();
}
......@@ -1391,65 +1401,6 @@ MaybeObject* KeyedLoadIC::Load(Handle<Object> object,
}
Handle<Code> KeyedLoadIC::CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver,
Handle<String> name,
Handle<Object> value) {
// Compute a monomorphic stub.
Handle<JSObject> holder(lookup->holder(), isolate());
switch (lookup->type()) {
case FIELD:
return isolate()->stub_cache()->ComputeKeyedLoadField(
name, receiver, holder,
lookup->GetFieldIndex(), lookup->representation());
case CONSTANT: {
Handle<Object> constant(lookup->GetConstant(), isolate());
// TODO(2803): Don't compute a stub for cons strings because they cannot
// be embedded into code.
if (constant->IsConsString()) return Handle<Code>::null();
return isolate()->stub_cache()->ComputeKeyedLoadConstant(
name, receiver, holder, constant);
}
case CALLBACKS: {
Handle<Object> callback_object(lookup->GetCallbackObject(), isolate());
// TODO(dcarney): Handle DeclaredAccessorInfo correctly.
if (callback_object->IsExecutableAccessorInfo()) {
Handle<ExecutableAccessorInfo> callback =
Handle<ExecutableAccessorInfo>::cast(callback_object);
if (v8::ToCData<Address>(callback->getter()) == 0) break;
if (!callback->IsCompatibleReceiver(*receiver)) break;
return isolate()->stub_cache()->ComputeKeyedLoadCallback(
name, receiver, holder, callback);
} else if (callback_object->IsAccessorPair()) {
Handle<Object> getter(
Handle<AccessorPair>::cast(callback_object)->getter(),
isolate());
if (!getter->IsJSFunction()) break;
if (holder->IsGlobalObject()) break;
if (!holder->HasFastProperties()) break;
Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() &&
call_optimization.IsCompatibleReceiver(*receiver)) {
return isolate()->stub_cache()->ComputeKeyedLoadCallback(
name, receiver, holder, call_optimization);
}
}
break;
}
case INTERCEPTOR:
ASSERT(HasInterceptorGetter(lookup->holder()));
return isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
name, receiver, holder);
default:
// Always rewrite to the generic case so that we do not
// repeatedly try to rewrite.
return generic_stub();
}
return Handle<Code>::null();
}
static bool LookupForWrite(Handle<JSObject> receiver,
Handle<String> name,
Handle<Object> value,
......@@ -1647,11 +1598,27 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
Handle<String> name,
Handle<Object> value) {
Handle<JSObject> holder(lookup->holder());
StoreStubCompiler compiler(isolate(), strict_mode(), kind());
switch (lookup->type()) {
case FIELD:
return isolate()->stub_cache()->ComputeStoreField(
name, receiver, lookup, strict_mode());
return compiler.CompileStoreField(receiver, lookup, name);
case TRANSITION: {
// Explicitly pass in the receiver map since LookupForWrite may have
// stored something else than the receiver in the holder.
Handle<Map> transition(
lookup->GetTransitionTarget(receiver->map()), isolate());
int descriptor = transition->LastAdded();
DescriptorArray* target_descriptors = transition->instance_descriptors();
PropertyDetails details = target_descriptors->GetDetails(descriptor);
if (details.type() == CALLBACKS || details.attributes() != NONE) break;
return compiler.CompileStoreTransition(
receiver, lookup, transition, name);
}
case NORMAL:
if (kind() == Code::KEYED_STORE_IC) break;
if (receiver->IsGlobalObject()) {
// The stub generated for the global object picks the value directly
// from the property cell. So the property must be directly on the
......@@ -1659,12 +1626,16 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
Handle<PropertyCell> cell(
global->GetPropertyCell(lookup), isolate());
// TODO(verwaest): Turn into a handler.
return isolate()->stub_cache()->ComputeStoreGlobal(
name, global, cell, value, strict_mode());
}
ASSERT(holder.is_identical_to(receiver));
return isolate()->stub_cache()->ComputeStoreNormal(strict_mode());
return strict_mode() == kStrictMode
? isolate()->builtins()->StoreIC_Normal_Strict()
: isolate()->builtins()->StoreIC_Normal();
case CALLBACKS: {
if (kind() == Code::KEYED_STORE_IC) break;
Handle<Object> callback(lookup->GetCallbackObject(), isolate());
if (callback->IsExecutableAccessorInfo()) {
Handle<ExecutableAccessorInfo> info =
......@@ -1672,8 +1643,7 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
if (v8::ToCData<Address>(info->setter()) == 0) break;
if (!holder->HasFastProperties()) break;
if (!info->IsCompatibleReceiver(*receiver)) break;
return isolate()->stub_cache()->ComputeStoreCallback(
name, receiver, holder, info, strict_mode());
return compiler.CompileStoreCallback(receiver, holder, name, info);
} else if (callback->IsAccessorPair()) {
Handle<Object> setter(
Handle<AccessorPair>::cast(callback)->setter(), isolate());
......@@ -1684,12 +1654,11 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() &&
call_optimization.IsCompatibleReceiver(*receiver)) {
return isolate()->stub_cache()->ComputeStoreCallback(
name, receiver, holder, call_optimization, strict_mode());
return compiler.CompileStoreCallback(
receiver, holder, name, call_optimization);
}
return isolate()->stub_cache()->ComputeStoreViaSetter(
name, receiver, holder, Handle<JSFunction>::cast(setter),
strict_mode());
return compiler.CompileStoreViaSetter(
receiver, holder, name, Handle<JSFunction>::cast(setter));
}
// TODO(dcarney): Handle correctly.
if (callback->IsDeclaredAccessorInfo()) break;
......@@ -1698,32 +1667,17 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
break;
}
case INTERCEPTOR:
if (kind() == Code::KEYED_STORE_IC) break;
ASSERT(HasInterceptorSetter(*receiver));
return isolate()->stub_cache()->ComputeStoreInterceptor(
name, receiver, strict_mode());
return compiler.CompileStoreInterceptor(receiver, name);
case CONSTANT:
break;
case TRANSITION: {
// Explicitly pass in the receiver map since LookupForWrite may have
// stored something else than the receiver in the holder.
Handle<Map> transition(
lookup->GetTransitionTarget(receiver->map()), isolate());
int descriptor = transition->LastAdded();
DescriptorArray* target_descriptors = transition->instance_descriptors();
PropertyDetails details = target_descriptors->GetDetails(descriptor);
if (details.type() == CALLBACKS || details.attributes() != NONE) break;
return isolate()->stub_cache()->ComputeStoreTransition(
name, receiver, lookup, transition, strict_mode());
}
case NONEXISTENT:
case HANDLER:
UNREACHABLE();
break;
}
return Handle<Code>::null();
return slow_stub();
}
......@@ -2034,49 +1988,6 @@ MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
}
Handle<Code> KeyedStoreIC::CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver,
Handle<String> name,
Handle<Object> value) {
// If the property has a non-field type allowing map transitions
// where there is extra room in the object, we leave the IC in its
// current state.
switch (lookup->type()) {
case FIELD:
return isolate()->stub_cache()->ComputeKeyedStoreField(
name, receiver, lookup, strict_mode());
case TRANSITION: {
// Explicitly pass in the receiver map since LookupForWrite may have
// stored something else than the receiver in the holder.
Handle<Map> transition(
lookup->GetTransitionTarget(receiver->map()), isolate());
int descriptor = transition->LastAdded();
DescriptorArray* target_descriptors = transition->instance_descriptors();
PropertyDetails details = target_descriptors->GetDetails(descriptor);
if (details.type() != CALLBACKS && details.attributes() == NONE) {
return isolate()->stub_cache()->ComputeKeyedStoreTransition(
name, receiver, lookup, transition, strict_mode());
}
// fall through.
}
case NORMAL:
case CONSTANT:
case CALLBACKS:
case INTERCEPTOR:
// Always rewrite to the generic case so that we do not
// repeatedly try to rewrite.
return generic_stub();
case HANDLER:
case NONEXISTENT:
UNREACHABLE();
break;
}
return Handle<Code>::null();
}
#undef TRACE_IC
......
......@@ -434,6 +434,11 @@ class LoadIC: public IC {
return pre_monomorphic_stub(isolate());
}
Handle<Code> SimpleFieldLoad(int offset,
bool inobject = true,
Representation representation =
Representation::Tagged());
static void Clear(Isolate* isolate, Address address, Code* target);
friend class IC;
......@@ -493,10 +498,6 @@ class KeyedLoadIC: public LoadIC {
return isolate()->builtins()->KeyedLoadIC_Slow();
}
virtual Handle<Code> CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver,
Handle<String> name,
Handle<Object> unused);
virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { }
private:
......@@ -680,10 +681,6 @@ class KeyedStoreIC: public StoreIC {
protected:
virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
virtual Handle<Code> CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver,
Handle<String> name,
Handle<Object> value);
virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { }
virtual Handle<Code> pre_monomorphic_stub() {
......
......@@ -202,78 +202,6 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
}
Handle<Code> StubCache::ComputeLoadField(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
PropertyIndex field,
Representation representation) {
if (receiver.is_identical_to(holder)) {
LoadFieldStub stub(field.is_inobject(holder),
field.translate(holder),
representation);
return stub.GetCode(isolate());
}
LoadStubCompiler compiler(isolate_);
return compiler.CompileLoadField(
receiver, holder, name, field, representation);
}
Handle<Code> StubCache::ComputeLoadCallback(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
LoadStubCompiler compiler(isolate_);
return compiler.CompileLoadCallback(receiver, holder, name, callback);
}
Handle<Code> StubCache::ComputeLoadCallback(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
const CallOptimization& call_optimization) {
LoadStubCompiler compiler(isolate_);
return compiler.CompileLoadCallback(
receiver, holder, name, call_optimization);
}
Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> getter) {
LoadStubCompiler compiler(isolate_);
return compiler.CompileLoadViaGetter(receiver, holder, name, getter);
}
Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<Object> value) {
LoadStubCompiler compiler(isolate_);
return compiler.CompileLoadConstant(receiver, holder, name, value);
}
Handle<Code> StubCache::ComputeLoadInterceptor(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder) {
LoadStubCompiler compiler(isolate_);
return compiler.CompileLoadInterceptor(receiver, holder, name);
}
Handle<Code> StubCache::ComputeLoadNormal(Handle<Name> name,
Handle<JSObject> receiver) {
return isolate_->builtins()->LoadIC_Normal();
}
Handle<Code> StubCache::ComputeLoadGlobal(Handle<Name> name,
Handle<JSObject> receiver,
Handle<GlobalObject> holder,
......@@ -290,83 +218,6 @@ Handle<Code> StubCache::ComputeLoadGlobal(Handle<Name> name,
}
Handle<Code> StubCache::ComputeKeyedLoadField(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
PropertyIndex field,
Representation representation) {
if (receiver.is_identical_to(holder)) {
// TODO(titzer): this should use an HObjectAccess
KeyedLoadFieldStub stub(field.is_inobject(holder),
field.translate(holder),
representation);
return stub.GetCode(isolate());
}
KeyedLoadStubCompiler compiler(isolate_);
return compiler.CompileLoadField(
receiver, holder, name, field, representation);
}
Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<Object> value) {
KeyedLoadStubCompiler compiler(isolate_);
return compiler.CompileLoadConstant(
receiver, holder, name, value);
}
Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder) {
KeyedLoadStubCompiler compiler(isolate_);
return compiler.CompileLoadInterceptor(receiver, holder, name);
}
Handle<Code> StubCache::ComputeKeyedLoadCallback(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
KeyedLoadStubCompiler compiler(isolate_);
return compiler.CompileLoadCallback(receiver, holder, name, callback);
}
Handle<Code> StubCache::ComputeKeyedLoadCallback(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
const CallOptimization& call_optimization) {
KeyedLoadStubCompiler compiler(isolate_);
return compiler.CompileLoadCallback(
receiver, holder, name, call_optimization);
}
Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
Handle<JSObject> receiver,
LookupResult* lookup,
StrictModeFlag strict_mode) {
StoreStubCompiler compiler(isolate_, strict_mode);
return compiler.CompileStoreField(receiver, lookup, name);
}
Handle<Code> StubCache::ComputeStoreTransition(Handle<Name> name,
Handle<JSObject> receiver,
LookupResult* lookup,
Handle<Map> transition,
StrictModeFlag strict_mode) {
StoreStubCompiler compiler(isolate_, strict_mode);
return compiler.CompileStoreTransition(receiver, lookup, transition, name);
}
Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) {
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC);
Handle<Name> name =
......@@ -411,13 +262,6 @@ Handle<Code> StubCache::ComputeKeyedStoreElement(
}
Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
return (strict_mode == kStrictMode)
? isolate_->builtins()->Builtins::StoreIC_Normal_Strict()
: isolate_->builtins()->Builtins::StoreIC_Normal();
}
Handle<Code> StubCache::ComputeStoreGlobal(Handle<Name> name,
Handle<GlobalObject> receiver,
Handle<PropertyCell> cell,
......@@ -448,68 +292,6 @@ Handle<Code> StubCache::ComputeStoreGlobal(Handle<Name> name,
}
Handle<Code> StubCache::ComputeStoreCallback(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback,
StrictModeFlag strict_mode) {
ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
StoreStubCompiler compiler(isolate_, strict_mode);
return compiler.CompileStoreCallback(receiver, holder, name, callback);
}
Handle<Code> StubCache::ComputeStoreCallback(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
const CallOptimization& call_optimization,
StrictModeFlag strict_mode) {
StoreStubCompiler compiler(isolate_, strict_mode);
return compiler.CompileStoreCallback(
receiver, holder, name, call_optimization);
}
Handle<Code> StubCache::ComputeStoreViaSetter(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> setter,
StrictModeFlag strict_mode) {
StoreStubCompiler compiler(isolate_, strict_mode);
return compiler.CompileStoreViaSetter(receiver, holder, name, setter);
}
Handle<Code> StubCache::ComputeStoreInterceptor(Handle<Name> name,
Handle<JSObject> receiver,
StrictModeFlag strict_mode) {
StoreStubCompiler compiler(isolate_, strict_mode);
return compiler.CompileStoreInterceptor(receiver, name);
}
Handle<Code> StubCache::ComputeKeyedStoreField(Handle<Name> name,
Handle<JSObject> receiver,
LookupResult* lookup,
StrictModeFlag strict_mode) {
KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE);
return compiler.CompileStoreField(receiver, lookup, name);
}
Handle<Code> StubCache::ComputeKeyedStoreTransition(
Handle<Name> name,
Handle<JSObject> receiver,
LookupResult* lookup,
Handle<Map> transition,
StrictModeFlag strict_mode) {
KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE);
return compiler.CompileStoreTransition(receiver, lookup, transition, name);
}
#define CALL_LOGGER_TAG(kind, type) \
(kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
......@@ -1387,7 +1169,7 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
#define __ ACCESS_MASM(masm())
Register BaseLoadStubCompiler::HandlerFrontendHeader(
Register LoadStubCompiler::HandlerFrontendHeader(
Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
......@@ -1401,7 +1183,7 @@ Register BaseLoadStubCompiler::HandlerFrontendHeader(
// HandlerFrontend for store uses the name register. It has to be restored
// before a miss.
Register BaseStoreStubCompiler::HandlerFrontendHeader(
Register StoreStubCompiler::HandlerFrontendHeader(
Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
......@@ -1427,7 +1209,7 @@ Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<JSObject> object,
}
Handle<Code> BaseLoadStubCompiler::CompileLoadField(
Handle<Code> LoadStubCompiler::CompileLoadField(
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
......@@ -1447,7 +1229,7 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadField(
}
Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
Handle<Code> LoadStubCompiler::CompileLoadConstant(
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
......@@ -1462,7 +1244,7 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
}
Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
Handle<Code> LoadStubCompiler::CompileLoadCallback(
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
......@@ -1479,7 +1261,7 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
}
Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
Handle<Code> LoadStubCompiler::CompileLoadCallback(
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
......@@ -1498,7 +1280,7 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
}
Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor(
Handle<Code> LoadStubCompiler::CompileLoadInterceptor(
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name) {
......@@ -1518,7 +1300,7 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor(
}
void BaseLoadStubCompiler::GenerateLoadPostInterceptor(
void LoadStubCompiler::GenerateLoadPostInterceptor(
Register interceptor_reg,
Handle<JSObject> interceptor_holder,
Handle<Name> name,
......@@ -1577,14 +1359,14 @@ Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
GenerateLoadViaGetter(masm(), getter);
GenerateLoadViaGetter(masm(), receiver(), getter);
// Return the generated code.
return GetCode(kind(), Code::CALLBACKS, name);
}
Handle<Code> BaseStoreStubCompiler::CompileStoreTransition(
Handle<Code> StoreStubCompiler::CompileStoreTransition(
Handle<JSObject> object,
LookupResult* lookup,
Handle<Map> transition,
......@@ -1641,9 +1423,9 @@ Handle<Code> BaseStoreStubCompiler::CompileStoreTransition(
}
Handle<Code> BaseStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
LookupResult* lookup,
Handle<Name> name) {
Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
LookupResult* lookup,
Handle<Name> name) {
Label miss;
HandlerFrontendHeader(object, receiver(), object, name, &miss);
......@@ -1736,23 +1518,33 @@ void StubCompiler::TailCallBuiltin(MacroAssembler* masm, Builtins::Name name) {
}
void LoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
}
void KeyedLoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
}
void StoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
void BaseLoadStoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
#ifdef ENABLE_GDB_JIT_INTERFACE
GDBJITInterface::CodeTag tag;
if (kind_ == Code::LOAD_IC) {
tag = GDBJITInterface::LOAD_IC;
} else if (kind_ == Code::KEYED_LOAD_IC) {
tag = GDBJITInterface::KEYED_LOAD_IC;
} else if (kind_ == Code::STORE_IC) {
tag = GDBJITInterface::STORE_IC;
} else {
tag = GDBJITInterface::KEYED_STORE_IC;
}
GDBJIT(AddCode(tag, *name, *code));
#endif
}
void KeyedStoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
void BaseLoadStoreStubCompiler::InitializeRegisters() {
if (kind_ == Code::LOAD_IC) {
registers_ = LoadStubCompiler::registers();
} else if (kind_ == Code::KEYED_LOAD_IC) {
registers_ = KeyedLoadStubCompiler::registers();
} else if (kind_ == Code::STORE_IC) {
registers_ = StoreStubCompiler::registers();
} else {
registers_ = KeyedStoreStubCompiler::registers();
}
}
......
......@@ -105,39 +105,6 @@ class StubCache {
Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
Handle<JSObject> object);
Handle<Code> ComputeLoadField(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
PropertyIndex field_index,
Representation representation);
Handle<Code> ComputeLoadCallback(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback);
Handle<Code> ComputeLoadCallback(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
const CallOptimization& call_optimization);
Handle<Code> ComputeLoadViaGetter(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<JSFunction> getter);
Handle<Code> ComputeLoadConstant(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Object> value);
Handle<Code> ComputeLoadInterceptor(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder);
Handle<Code> ComputeLoadNormal(Handle<Name> name,
Handle<JSObject> object);
Handle<Code> ComputeLoadGlobal(Handle<Name> name,
Handle<JSObject> object,
Handle<GlobalObject> holder,
......@@ -173,69 +140,18 @@ class StubCache {
Handle<JSObject> object,
Handle<JSObject> holder);
// ---
Handle<Code> ComputeStoreField(Handle<Name> name,
Handle<JSObject> object,
LookupResult* lookup,
StrictModeFlag strict_mode);
Handle<Code> ComputeStoreTransition(Handle<Name> name,
Handle<JSObject> object,
LookupResult* lookup,
Handle<Map> transition,
StrictModeFlag strict_mode);
Handle<Code> ComputeStoreNormal(StrictModeFlag strict_mode);
Handle<Code> ComputeStoreGlobal(Handle<Name> name,
Handle<GlobalObject> object,
Handle<PropertyCell> cell,
Handle<Object> value,
StrictModeFlag strict_mode);
Handle<Code> ComputeStoreCallback(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback,
StrictModeFlag strict_mode);
Handle<Code> ComputeStoreCallback(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
const CallOptimization& call_optimation,
StrictModeFlag strict_mode);
Handle<Code> ComputeStoreViaSetter(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<JSFunction> setter,
StrictModeFlag strict_mode);
Handle<Code> ComputeStoreInterceptor(Handle<Name> name,
Handle<JSObject> object,
StrictModeFlag strict_mode);
// ---
Handle<Code> ComputeKeyedStoreField(Handle<Name> name,
Handle<JSObject> object,
LookupResult* lookup,
StrictModeFlag strict_mode);
Handle<Code> ComputeKeyedStoreTransition(Handle<Name> name,
Handle<JSObject> object,
LookupResult* lookup,
Handle<Map> transition,
StrictModeFlag strict_mode);
Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map);
Handle<Code> ComputeKeyedStoreElement(Handle<Map> receiver_map,
StrictModeFlag strict_mode,
KeyedAccessStoreMode store_mode);
// ---
Handle<Code> ComputeCallField(int argc,
Code::Kind,
Code::ExtraICState extra_state,
......@@ -624,8 +540,10 @@ enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS };
class BaseLoadStoreStubCompiler: public StubCompiler {
public:
BaseLoadStoreStubCompiler(Isolate* isolate, Register* registers)
: StubCompiler(isolate), registers_(registers) { }
BaseLoadStoreStubCompiler(Isolate* isolate, Code::Kind kind)
: StubCompiler(isolate), kind_(kind) {
InitializeRegisters();
}
virtual ~BaseLoadStoreStubCompiler() { }
Handle<Code> CompileMonomorphicIC(Handle<Map> receiver_map,
......@@ -678,26 +596,45 @@ class BaseLoadStoreStubCompiler: public StubCompiler {
Code::StubType type,
Handle<Name> name,
InlineCacheState state = MONOMORPHIC);
Code::Kind kind() { return kind_; }
Logger::LogEventsAndTags log_kind(Handle<Code> code) {
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
if (kind_ == Code::LOAD_IC) {
return code->ic_state() == MONOMORPHIC
? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
} else if (kind_ == Code::KEYED_LOAD_IC) {
return code->ic_state() == MONOMORPHIC
? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
} else if (kind_ == Code::STORE_IC) {
return code->ic_state() == MONOMORPHIC
? Logger::STORE_IC_TAG : Logger::STORE_POLYMORPHIC_IC_TAG;
} else {
return code->ic_state() == MONOMORPHIC
? Logger::KEYED_STORE_IC_TAG : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG;
}
}
void JitEvent(Handle<Name> name, Handle<Code> code);
virtual Code::ExtraICState extra_state() { return Code::kNoExtraICState; }
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) = 0;
virtual void JitEvent(Handle<Name> name, Handle<Code> code) = 0;
virtual Code::Kind kind() = 0;
virtual Register receiver() = 0;
virtual Register name() = 0;
virtual Register scratch1() = 0;
virtual Register scratch2() = 0;
virtual Register scratch3() = 0;
void InitializeRegisters();
Code::Kind kind_;
Register* registers_;
};
class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler {
class LoadStubCompiler: public BaseLoadStoreStubCompiler {
public:
BaseLoadStubCompiler(Isolate* isolate, Register* registers)
: BaseLoadStoreStubCompiler(isolate, registers) { }
virtual ~BaseLoadStubCompiler() { }
LoadStubCompiler(Isolate* isolate, Code::Kind kind = Code::LOAD_IC)
: BaseLoadStoreStubCompiler(isolate, kind) { }
virtual ~LoadStubCompiler() { }
Handle<Code> CompileLoadField(Handle<JSObject> object,
Handle<JSObject> holder,
......@@ -724,6 +661,28 @@ class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler {
Handle<JSObject> holder,
Handle<Name> name);
Handle<Code> CompileLoadViaGetter(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<JSFunction> getter);
static void GenerateLoadViaGetter(MacroAssembler* masm,
Register receiver,
Handle<JSFunction> getter);
Handle<Code> CompileLoadNonexistent(Handle<JSObject> object,
Handle<JSObject> last,
Handle<Name> name,
Handle<GlobalObject> global);
Handle<Code> CompileLoadGlobal(Handle<JSObject> object,
Handle<GlobalObject> holder,
Handle<PropertyCell> cell,
Handle<Name> name,
bool is_dont_delete);
static Register* registers();
protected:
virtual Register HandlerFrontendHeader(Handle<JSObject> object,
Register object_reg,
......@@ -774,46 +733,10 @@ class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler {
};
class LoadStubCompiler: public BaseLoadStubCompiler {
public:
explicit LoadStubCompiler(Isolate* isolate)
: BaseLoadStubCompiler(isolate, registers()) { }
Handle<Code> CompileLoadNonexistent(Handle<JSObject> object,
Handle<JSObject> last,
Handle<Name> name,
Handle<GlobalObject> global);
static void GenerateLoadViaGetter(MacroAssembler* masm,
Handle<JSFunction> getter);
Handle<Code> CompileLoadViaGetter(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<JSFunction> getter);
Handle<Code> CompileLoadGlobal(Handle<JSObject> object,
Handle<GlobalObject> holder,
Handle<PropertyCell> cell,
Handle<Name> name,
bool is_dont_delete);
private:
static Register* registers();
virtual Code::Kind kind() { return Code::LOAD_IC; }
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
return code->ic_state() == MONOMORPHIC
? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
}
virtual void JitEvent(Handle<Name> name, Handle<Code> code);
};
class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
class KeyedLoadStubCompiler: public LoadStubCompiler {
public:
explicit KeyedLoadStubCompiler(Isolate* isolate)
: BaseLoadStubCompiler(isolate, registers()) { }
: LoadStubCompiler(isolate, Code::KEYED_LOAD_IC) { }
Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
......@@ -822,30 +745,26 @@ class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
static void GenerateLoadDictionaryElement(MacroAssembler* masm);
private:
protected:
static Register* registers();
virtual Code::Kind kind() { return Code::KEYED_LOAD_IC; }
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
return code->ic_state() == MONOMORPHIC
? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
}
virtual void JitEvent(Handle<Name> name, Handle<Code> code);
private:
virtual void GenerateNameCheck(Handle<Name> name,
Register name_reg,
Label* miss);
friend class BaseLoadStoreStubCompiler;
};
class BaseStoreStubCompiler: public BaseLoadStoreStubCompiler {
class StoreStubCompiler: public BaseLoadStoreStubCompiler {
public:
BaseStoreStubCompiler(Isolate* isolate,
StrictModeFlag strict_mode,
Register* registers)
: BaseLoadStoreStubCompiler(isolate, registers),
StoreStubCompiler(Isolate* isolate,
StrictModeFlag strict_mode,
Code::Kind kind = Code::STORE_IC)
: BaseLoadStoreStubCompiler(isolate, kind),
strict_mode_(strict_mode) { }
virtual ~BaseStoreStubCompiler() { }
virtual ~StoreStubCompiler() { }
Handle<Code> CompileStoreTransition(Handle<JSObject> object,
LookupResult* lookup,
......@@ -886,16 +805,27 @@ class BaseStoreStubCompiler: public BaseLoadStoreStubCompiler {
Register scratch2,
Label* miss_label);
static Builtins::Name MissBuiltin(Code::Kind kind) {
switch (kind) {
case Code::LOAD_IC: return Builtins::kLoadIC_Miss;
case Code::STORE_IC: return Builtins::kStoreIC_Miss;
case Code::KEYED_LOAD_IC: return Builtins::kKeyedLoadIC_Miss;
case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Miss;
default: UNREACHABLE();
}
return Builtins::kLoadIC_Miss;
}
Handle<Code> CompileStoreCallback(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<ExecutableAccessorInfo> callback);
Handle<Code> CompileStoreCallback(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization);
static void GenerateStoreViaSetter(MacroAssembler* masm,
Handle<JSFunction> setter);
Handle<Code> CompileStoreViaSetter(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<JSFunction> setter);
Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
Handle<Name> name);
static Builtins::Name SlowBuiltin(Code::Kind kind) {
switch (kind) {
case Code::STORE_IC: return Builtins::kStoreIC_Slow;
......@@ -928,56 +858,21 @@ class BaseStoreStubCompiler: public BaseLoadStoreStubCompiler {
StrictModeFlag strict_mode() { return strict_mode_; }
virtual Code::ExtraICState extra_state() { return strict_mode_; }
private:
StrictModeFlag strict_mode_;
};
class StoreStubCompiler: public BaseStoreStubCompiler {
public:
StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
: BaseStoreStubCompiler(isolate, strict_mode, registers()) { }
Handle<Code> CompileStoreCallback(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<ExecutableAccessorInfo> callback);
Handle<Code> CompileStoreCallback(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization);
static void GenerateStoreViaSetter(MacroAssembler* masm,
Handle<JSFunction> setter);
Handle<Code> CompileStoreViaSetter(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<JSFunction> setter);
Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
Handle<Name> name);
protected:
static Register* registers();
private:
static Register* registers();
virtual Code::Kind kind() { return Code::STORE_IC; }
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
return code->ic_state() == MONOMORPHIC
? Logger::STORE_IC_TAG : Logger::STORE_POLYMORPHIC_IC_TAG;
}
virtual void JitEvent(Handle<Name> name, Handle<Code> code);
StrictModeFlag strict_mode_;
friend class BaseLoadStoreStubCompiler;
};
class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
class KeyedStoreStubCompiler: public StoreStubCompiler {
public:
KeyedStoreStubCompiler(Isolate* isolate,
StrictModeFlag strict_mode,
KeyedAccessStoreMode store_mode)
: BaseStoreStubCompiler(isolate, strict_mode, registers()),
: StoreStubCompiler(isolate, strict_mode, Code::KEYED_STORE_IC),
store_mode_(store_mode) { }
Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
......@@ -994,24 +889,18 @@ class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
virtual Code::ExtraICState extra_state() {
return Code::ComputeExtraICState(store_mode_, strict_mode());
}
static Register* registers();
private:
Register transition_map() {
return registers()[3];
}
static Register* registers();
virtual Code::Kind kind() { return Code::KEYED_STORE_IC; }
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
return code->ic_state() == MONOMORPHIC
? Logger::KEYED_STORE_IC_TAG : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG;
}
virtual void JitEvent(Handle<Name> name, Handle<Code> code);
virtual void GenerateNameCheck(Handle<Name> name,
Register name_reg,
Label* miss);
KeyedAccessStoreMode store_mode_;
friend class BaseLoadStoreStubCompiler;
};
......
......@@ -767,9 +767,9 @@ class CallInterceptorCompiler BASE_EMBEDDED {
};
void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
Label* label,
Handle<Name> name) {
void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
Label* label,
Handle<Name> name) {
if (!label->is_unused()) {
__ bind(label);
__ Move(this->name(), name);
......@@ -795,7 +795,7 @@ static void GenerateCheckPropertyCell(MacroAssembler* masm,
}
void BaseStoreStubCompiler::GenerateNegativeHolderLookup(
void StoreStubCompiler::GenerateNegativeHolderLookup(
MacroAssembler* masm,
Handle<JSObject> holder,
Register holder_reg,
......@@ -813,19 +813,19 @@ void BaseStoreStubCompiler::GenerateNegativeHolderLookup(
// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
// store is successful.
void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
Register receiver_reg,
Register storage_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Register unused,
Label* miss_label,
Label* slow) {
void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
Register receiver_reg,
Register storage_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Register unused,
Label* miss_label,
Label* slow) {
int descriptor = transition->LastAdded();
DescriptorArray* descriptors = transition->instance_descriptors();
PropertyDetails details = descriptors->GetDetails(descriptor);
......@@ -958,15 +958,15 @@ void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
// Both name_reg and receiver_reg are preserved on jumps to miss_label,
// but may be destroyed if store is successful.
void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Register receiver_reg,
Register name_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Label* miss_label) {
void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object,
LookupResult* lookup,
Register receiver_reg,
Register name_reg,
Register value_reg,
Register scratch1,
Register scratch2,
Label* miss_label) {
// Stub never generated for non-global objects that require access
// checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
......@@ -1209,9 +1209,9 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
}
void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
if (!miss->is_unused()) {
__ jmp(success);
__ bind(miss);
......@@ -1220,9 +1220,9 @@ void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
}
void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
if (!miss->is_unused()) {
__ jmp(success);
GenerateRestoreName(masm(), miss, name);
......@@ -1231,7 +1231,7 @@ void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
}
Register BaseLoadStubCompiler::CallbackHandlerFrontend(
Register LoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
......@@ -1282,7 +1282,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend(
}
void BaseLoadStubCompiler::NonexistentHandlerFrontend(
void LoadStubCompiler::NonexistentHandlerFrontend(
Handle<JSObject> object,
Handle<JSObject> last,
Handle<Name> name,
......@@ -1302,7 +1302,7 @@ void BaseLoadStubCompiler::NonexistentHandlerFrontend(
}
void BaseLoadStubCompiler::GenerateLoadField(Register reg,
void LoadStubCompiler::GenerateLoadField(Register reg,
Handle<JSObject> holder,
PropertyIndex field,
Representation representation) {
......@@ -1321,14 +1321,14 @@ void BaseLoadStubCompiler::GenerateLoadField(Register reg,
}
void BaseLoadStubCompiler::GenerateLoadCallback(
void LoadStubCompiler::GenerateLoadCallback(
const CallOptimization& call_optimization) {
GenerateFastApiCall(
masm(), call_optimization, receiver(), scratch3(), 0, NULL);
}
void BaseLoadStubCompiler::GenerateLoadCallback(
void LoadStubCompiler::GenerateLoadCallback(
Register reg,
Handle<ExecutableAccessorInfo> callback) {
// Insert additional parameters into the stack frame above return address.
......@@ -1409,14 +1409,14 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
}
void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
// Return the constant value.
__ LoadObject(rax, value);
__ ret(0);
}
void BaseLoadStubCompiler::GenerateLoadInterceptor(
void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg,
Handle<JSObject> object,
Handle<JSObject> interceptor_holder,
......@@ -3022,6 +3022,7 @@ void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
Register receiver,
Handle<JSFunction> getter) {
// ----------- S t a t e -------------
// -- rax : receiver
......@@ -3033,7 +3034,7 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
if (!getter.is_null()) {
// Call the JavaScript getter with the receiver on the stack.
__ push(rax);
__ push(receiver);
ParameterCount actual(0);
ParameterCount expected(getter);
__ InvokeFunction(getter, expected, actual,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment