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 { ...@@ -50,7 +50,6 @@ namespace internal {
ICU(KeyedStoreIC_MissForceGeneric) \ ICU(KeyedStoreIC_MissForceGeneric) \
ICU(KeyedStoreIC_Slow) \ ICU(KeyedStoreIC_Slow) \
/* Utilities for IC stubs. */ \ /* Utilities for IC stubs. */ \
ICU(LoadCallbackProperty) \
ICU(StoreCallbackProperty) \ ICU(StoreCallbackProperty) \
ICU(LoadPropertyWithInterceptorOnly) \ ICU(LoadPropertyWithInterceptorOnly) \
ICU(LoadPropertyWithInterceptorForLoad) \ ICU(LoadPropertyWithInterceptorForLoad) \
......
...@@ -1016,32 +1016,6 @@ void StubCache::CollectMatchingMaps(SmallMapList* types, ...@@ -1016,32 +1016,6 @@ void StubCache::CollectMatchingMaps(SmallMapList* types,
// StubCompiler implementation. // 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) { RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
JSObject* recv = JSObject::cast(args[0]); JSObject* recv = JSObject::cast(args[0]);
ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[1]); ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[1]);
...@@ -1409,59 +1383,87 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder, ...@@ -1409,59 +1383,87 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
#define __ ACCESS_MASM(masm()) #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<Code> BaseLoadStubCompiler::CompileLoadField(Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<String> name, Handle<String> name,
PropertyIndex index) { PropertyIndex index) {
Label miss; Label success;
Register reg = HandlerFrontend(object, receiver(), holder, name,
GenerateNameCheck(name, this->name(), &miss); &success, PERFORM_INITIAL_CHECKS);
GenerateLoadField(object, holder, receiver(), __ bind(&success);
scratch1(), scratch2(), scratch3(), GenerateLoadField(reg, holder, index);
index, name, &miss);
__ bind(&miss);
GenerateLoadMiss(masm(), kind());
// Return the generated code. // Return the generated code.
return GetCode(Code::FIELD, name); return GetCode(Code::FIELD, name);
} }
Handle<Code> BaseLoadStubCompiler::CompileLoadCallback( Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<String> name, Handle<String> name,
Handle<ExecutableAccessorInfo> callback) { Handle<JSFunction> value) {
Label miss; Label success;
HandlerFrontend(object, receiver(), holder, name,
GenerateNameCheck(name, this->name(), &miss); &success, PERFORM_INITIAL_CHECKS);
GenerateLoadCallback(object, holder, receiver(), this->name(), __ bind(&success);
scratch1(), scratch2(), scratch3(), scratch4(), GenerateLoadConstant(value);
callback, name, &miss);
__ bind(&miss);
GenerateLoadMiss(masm(), kind());
// Return the generated code. // 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> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<String> name, Handle<String> name,
Handle<JSFunction> value) { Handle<ExecutableAccessorInfo> callback) {
Label miss; Label success;
GenerateNameCheck(name, this->name(), &miss); Register reg = CallbackHandlerFrontend(
GenerateLoadConstant(object, holder, receiver(), object, receiver(), holder, name, &success,
scratch1(), scratch2(), scratch3(), PERFORM_INITIAL_CHECKS, callback);
value, name, &miss); __ bind(&success);
__ bind(&miss); GenerateLoadCallback(reg, callback);
GenerateLoadMiss(masm(), kind());
// Return the generated code. // Return the generated code.
return GetCode(Code::CONSTANT_FUNCTION, name); return GetCode(Code::CALLBACKS, name);
} }
...@@ -1469,26 +1471,71 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor( ...@@ -1469,26 +1471,71 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor(
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<String> name) { Handle<String> name) {
Label miss; Label success;
LookupResult lookup(isolate()); LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup); 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 // TODO(368): Compile in the whole chain: all the interceptors in
// prototypes and ultimate answer. // prototypes and ultimate answer.
GenerateLoadInterceptor(object, holder, &lookup, receiver(), this->name(), GenerateLoadInterceptor(reg, object, holder, &lookup, name);
scratch1(), scratch2(), scratch3(),
name, &miss);
__ bind(&miss);
GenerateLoadMiss(masm(), kind());
// Return the generated code. // Return the generated code.
return GetCode(Code::INTERCEPTOR, name); 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 __ #undef __
......
...@@ -402,7 +402,6 @@ class StubCache { ...@@ -402,7 +402,6 @@ class StubCache {
// Support functions for IC stubs for callbacks. // Support functions for IC stubs for callbacks.
DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty);
DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty); DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
...@@ -536,58 +535,6 @@ class StubCompiler BASE_EMBEDDED { ...@@ -536,58 +535,6 @@ class StubCompiler BASE_EMBEDDED {
MacroAssembler* masm() { return &masm_; } MacroAssembler* masm() { return &masm_; }
void set_failure(Failure* failure) { failure_ = failure; } 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, static void LookupPostInterceptor(Handle<JSObject> holder,
Handle<String> name, Handle<String> name,
LookupResult* lookup); LookupResult* lookup);
...@@ -603,6 +550,9 @@ class StubCompiler BASE_EMBEDDED { ...@@ -603,6 +550,9 @@ class StubCompiler BASE_EMBEDDED {
}; };
enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS };
class BaseLoadStubCompiler: public StubCompiler { class BaseLoadStubCompiler: public StubCompiler {
public: public:
BaseLoadStubCompiler(Isolate* isolate, Register* registers) BaseLoadStubCompiler(Isolate* isolate, Register* registers)
...@@ -629,6 +579,50 @@ class BaseLoadStubCompiler: public StubCompiler { ...@@ -629,6 +579,50 @@ class BaseLoadStubCompiler: public StubCompiler {
Handle<String> name); Handle<String> name);
protected: 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 receiver() { return registers_[0]; }
Register name() { return registers_[1]; } Register name() { return registers_[1]; }
Register scratch1() { return registers_[2]; } Register scratch1() { return registers_[2]; }
......
This diff is collapsed.
...@@ -108,8 +108,6 @@ TEST(ExternalReferenceEncoder) { ...@@ -108,8 +108,6 @@ TEST(ExternalReferenceEncoder) {
Encode(encoder, Builtins::kArrayCode)); Encode(encoder, Builtins::kArrayCode));
CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort), CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort),
Encode(encoder, 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 keyed_load_function_prototype =
ExternalReference(isolate->counters()->keyed_load_function_prototype()); ExternalReference(isolate->counters()->keyed_load_function_prototype());
CHECK_EQ(make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype), CHECK_EQ(make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype),
...@@ -148,8 +146,6 @@ TEST(ExternalReferenceDecoder) { ...@@ -148,8 +146,6 @@ TEST(ExternalReferenceDecoder) {
CHECK_EQ(AddressOf(Runtime::kAbort), CHECK_EQ(AddressOf(Runtime::kAbort),
decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION, decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION,
Runtime::kAbort))); Runtime::kAbort)));
CHECK_EQ(AddressOf(IC_Utility(IC::kLoadCallbackProperty)),
decoder.Decode(make_code(IC_UTILITY, IC::kLoadCallbackProperty)));
ExternalReference keyed_load_function = ExternalReference keyed_load_function =
ExternalReference(isolate->counters()->keyed_load_function_prototype()); ExternalReference(isolate->counters()->keyed_load_function_prototype());
CHECK_EQ(keyed_load_function.address(), 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