Index: src/stub-cache.cc |
diff --git a/src/stub-cache.cc b/src/stub-cache.cc |
index 06b4782b767f4875a7fd271f3535a539c923715d..96aa50f01cf34819cba71c8182a36e1633e60248 100644 |
--- a/src/stub-cache.cc |
+++ b/src/stub-cache.cc |
@@ -1000,32 +1000,6 @@ void StubCache::CollectMatchingMaps(SmallMapList* types, |
// StubCompiler implementation. |
-RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) { |
- ASSERT(args[0]->IsJSObject()); |
- ASSERT(args[1]->IsJSObject()); |
- ASSERT(args[3]->IsSmi()); |
- AccessorInfo* callback = AccessorInfo::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]); |
AccessorInfo* callback = AccessorInfo::cast(args[1]); |
@@ -1393,59 +1367,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<AccessorInfo> 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<AccessorInfo> 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); |
} |
@@ -1453,26 +1455,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<AccessorInfo> callback( |
+ AccessorInfo::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 __ |