Commit 3ab255f5 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Currently this mostly just moves code around.

- Later the different parts will become individual code objects that tailcall into one another.
- The mapcheck/symbol check still needs to be separated from the overall prototype-chain check so that the ICs can reuse the handlers.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13768 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 574dc38f
This diff is collapsed.
This diff is collapsed.
......@@ -50,7 +50,6 @@ namespace internal {
ICU(KeyedStoreIC_MissForceGeneric) \
ICU(KeyedStoreIC_Slow) \
/* Utilities for IC stubs. */ \
ICU(LoadCallbackProperty) \
ICU(StoreCallbackProperty) \
ICU(LoadPropertyWithInterceptorOnly) \
ICU(LoadPropertyWithInterceptorForLoad) \
......
......@@ -1016,32 +1016,6 @@ void StubCache::CollectMatchingMaps(SmallMapList* types,
// StubCompiler implementation.
RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
ASSERT(args[0]->IsJSObject());
ASSERT(args[1]->IsJSObject());
ASSERT(args[3]->IsSmi());
ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[4]);
Address getter_address = v8::ToCData<Address>(callback->getter());
v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
ASSERT(fun != NULL);
ASSERT(callback->IsCompatibleReceiver(args[0]));
v8::AccessorInfo info(&args[0]);
HandleScope scope(isolate);
v8::Handle<v8::Value> result;
{
// Leaving JavaScript.
VMState state(isolate, EXTERNAL);
ExternalCallbackScope call_scope(isolate, getter_address);
result = fun(v8::Utils::ToLocal(args.at<String>(5)), info);
}
RETURN_IF_SCHEDULED_EXCEPTION(isolate);
if (result.IsEmpty()) return HEAP->undefined_value();
Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
result_internal->VerifyApiCallResultType();
return *result_internal;
}
RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
JSObject* recv = JSObject::cast(args[0]);
ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[1]);
......@@ -1409,59 +1383,87 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
#define __ ACCESS_MASM(masm())
Register BaseLoadStubCompiler::HandlerFrontendHeader(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
Handle<String> name,
Label* miss,
FrontendCheckType check) {
if (check == PERFORM_INITIAL_CHECKS) {
GenerateNameCheck(name, this->name(), miss);
// Check that the receiver isn't a smi.
__ JumpIfSmi(object_reg, miss);
}
// Check the prototype chain.
return CheckPrototypes(object, object_reg, holder,
scratch1(), scratch2(), scratch3(),
name, miss);
}
Register BaseLoadStubCompiler::HandlerFrontend(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
Handle<String> name,
Label* success,
FrontendCheckType check) {
Label miss;
Register reg = HandlerFrontendHeader(
object, object_reg, holder, name, &miss, check);
HandlerFrontendFooter(success, &miss);
return reg;
}
Handle<Code> BaseLoadStubCompiler::CompileLoadField(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<String> name,
PropertyIndex index) {
Label miss;
GenerateNameCheck(name, this->name(), &miss);
GenerateLoadField(object, holder, receiver(),
scratch1(), scratch2(), scratch3(),
index, name, &miss);
__ bind(&miss);
GenerateLoadMiss(masm(), kind());
Label success;
Register reg = HandlerFrontend(object, receiver(), holder, name,
&success, PERFORM_INITIAL_CHECKS);
__ bind(&success);
GenerateLoadField(reg, holder, index);
// Return the generated code.
return GetCode(Code::FIELD, name);
}
Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<String> name,
Handle<ExecutableAccessorInfo> callback) {
Label miss;
GenerateNameCheck(name, this->name(), &miss);
GenerateLoadCallback(object, holder, receiver(), this->name(),
scratch1(), scratch2(), scratch3(), scratch4(),
callback, name, &miss);
__ bind(&miss);
GenerateLoadMiss(masm(), kind());
Handle<JSFunction> value) {
Label success;
HandlerFrontend(object, receiver(), holder, name,
&success, PERFORM_INITIAL_CHECKS);
__ bind(&success);
GenerateLoadConstant(value);
// Return the generated code.
return GetCode(Code::CALLBACKS, name);
return GetCode(Code::CONSTANT_FUNCTION, name);
}
Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<String> name,
Handle<JSFunction> value) {
Label miss;
Handle<ExecutableAccessorInfo> callback) {
Label success;
GenerateNameCheck(name, this->name(), &miss);
GenerateLoadConstant(object, holder, receiver(),
scratch1(), scratch2(), scratch3(),
value, name, &miss);
__ bind(&miss);
GenerateLoadMiss(masm(), kind());
Register reg = CallbackHandlerFrontend(
object, receiver(), holder, name, &success,
PERFORM_INITIAL_CHECKS, callback);
__ bind(&success);
GenerateLoadCallback(reg, callback);
// Return the generated code.
return GetCode(Code::CONSTANT_FUNCTION, name);
return GetCode(Code::CALLBACKS, name);
}
......@@ -1469,26 +1471,71 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor(
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<String> name) {
Label miss;
Label success;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
GenerateNameCheck(name, this->name(), &miss);
Register reg = HandlerFrontend(object, receiver(), holder, name,
&success, PERFORM_INITIAL_CHECKS);
__ bind(&success);
// TODO(368): Compile in the whole chain: all the interceptors in
// prototypes and ultimate answer.
GenerateLoadInterceptor(object, holder, &lookup, receiver(), this->name(),
scratch1(), scratch2(), scratch3(),
name, &miss);
__ bind(&miss);
GenerateLoadMiss(masm(), kind());
GenerateLoadInterceptor(reg, object, holder, &lookup, name);
// Return the generated code.
return GetCode(Code::INTERCEPTOR, name);
}
void BaseLoadStubCompiler::GenerateLoadPostInterceptor(
Register interceptor_reg,
Handle<JSObject> interceptor_holder,
Handle<String> name,
LookupResult* lookup) {
Label success;
Handle<JSObject> holder(lookup->holder());
if (lookup->IsField()) {
// We found FIELD property in prototype chain of interceptor's holder.
// Retrieve a field from field's holder.
Register reg = HandlerFrontend(interceptor_holder, interceptor_reg, holder,
name, &success, SKIP_INITIAL_CHECKS);
__ bind(&success);
GenerateLoadField(reg, holder, lookup->GetFieldIndex());
} else {
// We found CALLBACKS property in prototype chain of interceptor's
// holder.
ASSERT(lookup->type() == CALLBACKS);
Handle<ExecutableAccessorInfo> callback(
ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
ASSERT(callback->getter() != NULL);
Register reg = CallbackHandlerFrontend(
interceptor_holder, interceptor_reg, holder,
name, &success, SKIP_INITIAL_CHECKS, callback);
__ bind(&success);
GenerateLoadCallback(reg, callback);
}
}
Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<String> name,
Handle<JSFunction> getter) {
Label success;
HandlerFrontend(object, receiver(), holder, name,
&success, PERFORM_INITIAL_CHECKS);
__ bind(&success);
GenerateLoadViaGetter(masm(), getter);
// Return the generated code.
return GetCode(Code::CALLBACKS, name);
}
#undef __
......
......@@ -402,7 +402,6 @@ class StubCache {
// Support functions for IC stubs for callbacks.
DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty);
DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
......@@ -536,58 +535,6 @@ class StubCompiler BASE_EMBEDDED {
MacroAssembler* masm() { return &masm_; }
void set_failure(Failure* failure) { failure_ = failure; }
void GenerateLoadField(Handle<JSObject> object,
Handle<JSObject> holder,
Register receiver,
Register scratch1,
Register scratch2,
Register scratch3,
PropertyIndex index,
Handle<String> name,
Label* miss);
void GenerateLoadCallback(Handle<JSObject> object,
Handle<JSObject> holder,
Register receiver,
Register name_reg,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch4,
Handle<ExecutableAccessorInfo> callback,
Handle<String> name,
Label* miss);
void GenerateDictionaryLoadCallback(Register receiver,
Register name_reg,
Register scratch1,
Register scratch2,
Register scratch3,
Handle<ExecutableAccessorInfo> callback,
Handle<String> name,
Label* miss);
void GenerateLoadConstant(Handle<JSObject> object,
Handle<JSObject> holder,
Register receiver,
Register scratch1,
Register scratch2,
Register scratch3,
Handle<JSFunction> value,
Handle<String> name,
Label* miss);
void GenerateLoadInterceptor(Handle<JSObject> object,
Handle<JSObject> holder,
LookupResult* lookup,
Register receiver,
Register name_reg,
Register scratch1,
Register scratch2,
Register scratch3,
Handle<String> name,
Label* miss);
static void LookupPostInterceptor(Handle<JSObject> holder,
Handle<String> name,
LookupResult* lookup);
......@@ -603,6 +550,9 @@ class StubCompiler BASE_EMBEDDED {
};
enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS };
class BaseLoadStubCompiler: public StubCompiler {
public:
BaseLoadStubCompiler(Isolate* isolate, Register* registers)
......@@ -629,6 +579,50 @@ class BaseLoadStubCompiler: public StubCompiler {
Handle<String> name);
protected:
Register HandlerFrontendHeader(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
Handle<String> name,
Label* success,
FrontendCheckType check);
void HandlerFrontendFooter(Label* success, Label* miss);
Register HandlerFrontend(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
Handle<String> name,
Label* success,
FrontendCheckType check);
Register CallbackHandlerFrontend(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
Handle<String> name,
Label* success,
FrontendCheckType check,
Handle<ExecutableAccessorInfo> callback);
void NonexistentHandlerFrontend(Handle<JSObject> object,
Handle<JSObject> last,
Handle<String> name,
Label* success,
Handle<GlobalObject> global);
void GenerateLoadField(Register reg,
Handle<JSObject> holder,
PropertyIndex index);
void GenerateLoadConstant(Handle<JSFunction> value);
void GenerateLoadCallback(Register reg,
Handle<ExecutableAccessorInfo> callback);
void GenerateLoadInterceptor(Register holder_reg,
Handle<JSObject> object,
Handle<JSObject> holder,
LookupResult* lookup,
Handle<String> name);
void GenerateLoadPostInterceptor(Register reg,
Handle<JSObject> interceptor_holder,
Handle<String> name,
LookupResult* lookup);
Register receiver() { return registers_[0]; }
Register name() { return registers_[1]; }
Register scratch1() { return registers_[2]; }
......
This diff is collapsed.
......@@ -108,8 +108,6 @@ TEST(ExternalReferenceEncoder) {
Encode(encoder, Builtins::kArrayCode));
CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort),
Encode(encoder, Runtime::kAbort));
CHECK_EQ(make_code(IC_UTILITY, IC::kLoadCallbackProperty),
Encode(encoder, IC_Utility(IC::kLoadCallbackProperty)));
ExternalReference keyed_load_function_prototype =
ExternalReference(isolate->counters()->keyed_load_function_prototype());
CHECK_EQ(make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype),
......@@ -148,8 +146,6 @@ TEST(ExternalReferenceDecoder) {
CHECK_EQ(AddressOf(Runtime::kAbort),
decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION,
Runtime::kAbort)));
CHECK_EQ(AddressOf(IC_Utility(IC::kLoadCallbackProperty)),
decoder.Decode(make_code(IC_UTILITY, IC::kLoadCallbackProperty)));
ExternalReference keyed_load_function =
ExternalReference(isolate->counters()->keyed_load_function_prototype());
CHECK_EQ(keyed_load_function.address(),
......
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