summaryrefslogtreecommitdiffstats
path: root/src/stub-cache.cc
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-05-10 14:33:55 +0100
committerSteve Block <steveblock@google.com>2010-05-10 15:08:22 +0100
commit6ded16be15dd865a9b21ea304d5273c8be299c87 (patch)
treeb3661ae5d929e233f7024223f3fad0f2a284cd6e /src/stub-cache.cc
parent6599b9dd3411791c9d89ab7efbfb4131e5664c48 (diff)
downloadandroid_external_v8-6ded16be15dd865a9b21ea304d5273c8be299c87.tar.gz
android_external_v8-6ded16be15dd865a9b21ea304d5273c8be299c87.tar.bz2
android_external_v8-6ded16be15dd865a9b21ea304d5273c8be299c87.zip
Update V8 to r4588
We're using WebKit r58033, as used by http://src.chromium.org/svn/releases/5.0.387.0/DEPS This requires http://v8.googlecode.com/svn/trunk@4465 but this version has a crashing bug for ARM. Instead we use http://v8.googlecode.com/svn/trunk@4588, which is used by http://src.chromium.org/svn/releases/6.0.399.0/DEPS Note that a trivial bug fix was required in arm/codegen-arm.cc. This is guarded with ANDROID. See http://code.google.com/p/v8/issues/detail?id=703 Change-Id: I459647a8286c4f8c7405f0c5581ecbf051a6f1e8
Diffstat (limited to 'src/stub-cache.cc')
-rw-r--r--src/stub-cache.cc219
1 files changed, 159 insertions, 60 deletions
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 577c2d77..f3532533 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -93,6 +93,38 @@ Code* StubCache::Set(String* name, Map* map, Code* code) {
}
+Object* StubCache::ComputeLoadNonexistent(String* name, JSObject* receiver) {
+ // If no global objects are present in the prototype chain, the load
+ // nonexistent IC stub can be shared for all names for a given map
+ // and we use the empty string for the map cache in that case. If
+ // there are global objects involved, we need to check global
+ // property cells in the stub and therefore the stub will be
+ // specific to the name.
+ String* cache_name = Heap::empty_string();
+ if (receiver->IsGlobalObject()) cache_name = name;
+ JSObject* last = receiver;
+ while (last->GetPrototype() != Heap::null_value()) {
+ last = JSObject::cast(last->GetPrototype());
+ if (last->IsGlobalObject()) cache_name = name;
+ }
+ // Compile the stub that is either shared for all names or
+ // name specific if there are global objects involved.
+ Code::Flags flags =
+ Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT);
+ Object* code = receiver->map()->FindInCodeCache(cache_name, flags);
+ if (code->IsUndefined()) {
+ LoadStubCompiler compiler;
+ code = compiler.CompileLoadNonexistent(cache_name, receiver, last);
+ if (code->IsFailure()) return code;
+ PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), cache_name));
+ Object* result =
+ receiver->map()->UpdateCodeCache(cache_name, Code::cast(code));
+ if (result->IsFailure()) return result;
+ }
+ return Set(name, receiver->map(), Code::cast(code));
+}
+
+
Object* StubCache::ComputeLoadField(String* name,
JSObject* receiver,
JSObject* holder,
@@ -103,7 +135,7 @@ Object* StubCache::ComputeLoadField(String* name,
LoadStubCompiler compiler;
code = compiler.CompileLoadField(receiver, holder, field_index, name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -122,7 +154,7 @@ Object* StubCache::ComputeLoadCallback(String* name,
LoadStubCompiler compiler;
code = compiler.CompileLoadCallback(name, receiver, holder, callback);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -141,7 +173,7 @@ Object* StubCache::ComputeLoadConstant(String* name,
LoadStubCompiler compiler;
code = compiler.CompileLoadConstant(receiver, holder, value, name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -158,7 +190,7 @@ Object* StubCache::ComputeLoadInterceptor(String* name,
LoadStubCompiler compiler;
code = compiler.CompileLoadInterceptor(receiver, holder, name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -187,7 +219,7 @@ Object* StubCache::ComputeLoadGlobal(String* name,
name,
is_dont_delete);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -205,7 +237,7 @@ Object* StubCache::ComputeKeyedLoadField(String* name,
KeyedLoadStubCompiler compiler;
code = compiler.CompileLoadField(name, receiver, holder, field_index);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -224,7 +256,7 @@ Object* StubCache::ComputeKeyedLoadConstant(String* name,
KeyedLoadStubCompiler compiler;
code = compiler.CompileLoadConstant(name, receiver, holder, value);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -242,7 +274,7 @@ Object* StubCache::ComputeKeyedLoadInterceptor(String* name,
KeyedLoadStubCompiler compiler;
code = compiler.CompileLoadInterceptor(receiver, holder, name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -261,7 +293,7 @@ Object* StubCache::ComputeKeyedLoadCallback(String* name,
KeyedLoadStubCompiler compiler;
code = compiler.CompileLoadCallback(name, receiver, holder, callback);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -279,7 +311,7 @@ Object* StubCache::ComputeKeyedLoadArrayLength(String* name,
KeyedLoadStubCompiler compiler;
code = compiler.CompileLoadArrayLength(name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -296,7 +328,7 @@ Object* StubCache::ComputeKeyedLoadStringLength(String* name,
KeyedLoadStubCompiler compiler;
code = compiler.CompileLoadStringLength(name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -313,7 +345,7 @@ Object* StubCache::ComputeKeyedLoadFunctionPrototype(String* name,
KeyedLoadStubCompiler compiler;
code = compiler.CompileLoadFunctionPrototype(name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -332,7 +364,7 @@ Object* StubCache::ComputeStoreField(String* name,
StoreStubCompiler compiler;
code = compiler.CompileStoreField(receiver, field_index, transition, name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -349,7 +381,7 @@ Object* StubCache::ComputeStoreGlobal(String* name,
StoreStubCompiler compiler;
code = compiler.CompileStoreGlobal(receiver, cell, name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -367,7 +399,7 @@ Object* StubCache::ComputeStoreCallback(String* name,
StoreStubCompiler compiler;
code = compiler.CompileStoreCallback(receiver, callback, name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -384,7 +416,7 @@ Object* StubCache::ComputeStoreInterceptor(String* name,
StoreStubCompiler compiler;
code = compiler.CompileStoreInterceptor(receiver, name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -401,7 +433,8 @@ Object* StubCache::ComputeKeyedStoreField(String* name, JSObject* receiver,
KeyedStoreStubCompiler compiler;
code = compiler.CompileStoreField(receiver, field_index, transition, name);
if (code->IsFailure()) return code;
- LOG(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(
+ Logger::KEYED_STORE_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -435,14 +468,6 @@ Object* StubCache::ComputeCallConstant(int argc,
argc);
Object* code = map->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
- if (object->IsJSObject()) {
- Object* opt =
- Top::LookupSpecialFunction(JSObject::cast(object), holder, function);
- if (opt->IsJSFunction()) {
- check = StubCompiler::JSARRAY_HAS_FAST_ELEMENTS_CHECK;
- function = JSFunction::cast(opt);
- }
- }
// If the function hasn't been compiled yet, we cannot do it now
// because it may cause GC. To avoid this issue, we return an
// internal error which will make sure we do not update any
@@ -453,7 +478,7 @@ Object* StubCache::ComputeCallConstant(int argc,
code = compiler.CompileCallConstant(object, holder, function, name, check);
if (code->IsFailure()) return code;
ASSERT_EQ(flags, Code::cast(code)->flags());
- LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
Object* result = map->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -490,7 +515,7 @@ Object* StubCache::ComputeCallField(int argc,
name);
if (code->IsFailure()) return code;
ASSERT_EQ(flags, Code::cast(code)->flags());
- LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
Object* result = map->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -526,7 +551,7 @@ Object* StubCache::ComputeCallInterceptor(int argc,
name);
if (code->IsFailure()) return code;
ASSERT_EQ(flags, Code::cast(code)->flags());
- LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
Object* result = map->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -564,7 +589,7 @@ Object* StubCache::ComputeCallGlobal(int argc,
code = compiler.CompileCallGlobal(receiver, holder, cell, function, name);
if (code->IsFailure()) return code;
ASSERT_EQ(flags, Code::cast(code)->flags());
- LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
+ PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return result;
}
@@ -709,8 +734,8 @@ Object* StubCache::ComputeLazyCompile(int argc) {
if (result->IsCode()) {
Code* code = Code::cast(result);
USE(code);
- LOG(CodeCreateEvent(Logger::LAZY_COMPILE_TAG,
- code, code->arguments_count()));
+ PROFILE(CodeCreateEvent(Logger::LAZY_COMPILE_TAG,
+ code, code->arguments_count()));
}
return result;
}
@@ -790,6 +815,10 @@ Object* StoreCallbackProperty(Arguments args) {
return *value;
}
+
+static const int kAccessorInfoOffsetInInterceptorArgs = 2;
+
+
/**
* Attempts to load a property with an interceptor (which must be present),
* but doesn't search the prototype chain.
@@ -798,11 +827,12 @@ Object* StoreCallbackProperty(Arguments args) {
* provide any value for the given name.
*/
Object* LoadPropertyWithInterceptorOnly(Arguments args) {
- JSObject* receiver_handle = JSObject::cast(args[0]);
- JSObject* holder_handle = JSObject::cast(args[1]);
- Handle<String> name_handle = args.at<String>(2);
- Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(3);
- Object* data_handle = args[4];
+ Handle<String> name_handle = args.at<String>(0);
+ Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
+ ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
+ ASSERT(args[2]->IsJSObject()); // Receiver.
+ ASSERT(args[3]->IsJSObject()); // Holder.
+ ASSERT(args.length() == 5); // Last arg is data object.
Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
v8::NamedPropertyGetter getter =
@@ -811,8 +841,8 @@ Object* LoadPropertyWithInterceptorOnly(Arguments args) {
{
// Use the interceptor getter.
- CustomArguments args(data_handle, receiver_handle, holder_handle);
- v8::AccessorInfo info(args.end());
+ v8::AccessorInfo info(args.arguments() -
+ kAccessorInfoOffsetInInterceptorArgs);
HandleScope scope;
v8::Handle<v8::Value> r;
{
@@ -850,11 +880,12 @@ static Object* ThrowReferenceError(String* name) {
static Object* LoadWithInterceptor(Arguments* args,
PropertyAttributes* attrs) {
- Handle<JSObject> receiver_handle = args->at<JSObject>(0);
- Handle<JSObject> holder_handle = args->at<JSObject>(1);
- Handle<String> name_handle = args->at<String>(2);
- Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(3);
- Handle<Object> data_handle = args->at<Object>(4);
+ Handle<String> name_handle = args->at<String>(0);
+ Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
+ ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
+ Handle<JSObject> receiver_handle = args->at<JSObject>(2);
+ Handle<JSObject> holder_handle = args->at<JSObject>(3);
+ ASSERT(args->length() == 5); // Last arg is data object.
Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
v8::NamedPropertyGetter getter =
@@ -863,8 +894,8 @@ static Object* LoadWithInterceptor(Arguments* args,
{
// Use the interceptor getter.
- CustomArguments args(*data_handle, *receiver_handle, *holder_handle);
- v8::AccessorInfo info(args.end());
+ v8::AccessorInfo info(args->arguments() -
+ kAccessorInfoOffsetInInterceptorArgs);
HandleScope scope;
v8::Handle<v8::Value> r;
{
@@ -899,7 +930,7 @@ Object* LoadPropertyWithInterceptorForLoad(Arguments args) {
// If the property is present, return it.
if (attr != ABSENT) return result;
- return ThrowReferenceError(String::cast(args[2]));
+ return ThrowReferenceError(String::cast(args[0]));
}
@@ -941,8 +972,8 @@ Object* StubCompiler::CompileCallInitialize(Code::Flags flags) {
Counters::call_initialize_stubs.Increment();
Code* code = Code::cast(result);
USE(code);
- LOG(CodeCreateEvent(Logger::CALL_INITIALIZE_TAG,
- code, code->arguments_count()));
+ PROFILE(CodeCreateEvent(Logger::CALL_INITIALIZE_TAG,
+ code, code->arguments_count()));
}
return result;
}
@@ -959,8 +990,8 @@ Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
Counters::call_premonomorphic_stubs.Increment();
Code* code = Code::cast(result);
USE(code);
- LOG(CodeCreateEvent(Logger::CALL_PRE_MONOMORPHIC_TAG,
- code, code->arguments_count()));
+ PROFILE(CodeCreateEvent(Logger::CALL_PRE_MONOMORPHIC_TAG,
+ code, code->arguments_count()));
}
return result;
}
@@ -975,8 +1006,8 @@ Object* StubCompiler::CompileCallNormal(Code::Flags flags) {
Counters::call_normal_stubs.Increment();
Code* code = Code::cast(result);
USE(code);
- LOG(CodeCreateEvent(Logger::CALL_NORMAL_TAG,
- code, code->arguments_count()));
+ PROFILE(CodeCreateEvent(Logger::CALL_NORMAL_TAG,
+ code, code->arguments_count()));
}
return result;
}
@@ -991,8 +1022,8 @@ Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
Counters::call_megamorphic_stubs.Increment();
Code* code = Code::cast(result);
USE(code);
- LOG(CodeCreateEvent(Logger::CALL_MEGAMORPHIC_TAG,
- code, code->arguments_count()));
+ PROFILE(CodeCreateEvent(Logger::CALL_MEGAMORPHIC_TAG,
+ code, code->arguments_count()));
}
return result;
}
@@ -1007,7 +1038,8 @@ Object* StubCompiler::CompileCallMiss(Code::Flags flags) {
Counters::call_megamorphic_stubs.Increment();
Code* code = Code::cast(result);
USE(code);
- LOG(CodeCreateEvent(Logger::CALL_MISS_TAG, code, code->arguments_count()));
+ PROFILE(CodeCreateEvent(Logger::CALL_MISS_TAG,
+ code, code->arguments_count()));
}
return result;
}
@@ -1021,8 +1053,8 @@ Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
if (!result->IsFailure()) {
Code* code = Code::cast(result);
USE(code);
- LOG(CodeCreateEvent(Logger::CALL_DEBUG_BREAK_TAG,
- code, code->arguments_count()));
+ PROFILE(CodeCreateEvent(Logger::CALL_DEBUG_BREAK_TAG,
+ code, code->arguments_count()));
}
return result;
}
@@ -1038,8 +1070,8 @@ Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
if (!result->IsFailure()) {
Code* code = Code::cast(result);
USE(code);
- LOG(CodeCreateEvent(Logger::CALL_DEBUG_PREPARE_STEP_IN_TAG,
- code, code->arguments_count()));
+ PROFILE(CodeCreateEvent(Logger::CALL_DEBUG_PREPARE_STEP_IN_TAG,
+ code, code->arguments_count()));
}
return result;
}
@@ -1126,10 +1158,77 @@ Object* ConstructStubCompiler::GetCode() {
if (!result->IsFailure()) {
Code* code = Code::cast(result);
USE(code);
- LOG(CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
+ PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
}
return result;
}
+CallOptimization::CallOptimization(LookupResult* lookup) {
+ if (!lookup->IsProperty() || !lookup->IsCacheable() ||
+ lookup->type() != CONSTANT_FUNCTION) {
+ Initialize(NULL);
+ } else {
+ // We only optimize constant function calls.
+ Initialize(lookup->GetConstantFunction());
+ }
+}
+
+CallOptimization::CallOptimization(JSFunction* function) {
+ Initialize(function);
+}
+
+
+int CallOptimization::GetPrototypeDepthOfExpectedType(JSObject* object,
+ JSObject* holder) const {
+ ASSERT(is_simple_api_call_);
+ if (expected_receiver_type_ == NULL) return 0;
+ int depth = 0;
+ while (object != holder) {
+ if (object->IsInstanceOf(expected_receiver_type_)) return depth;
+ object = JSObject::cast(object->GetPrototype());
+ ++depth;
+ }
+ if (holder->IsInstanceOf(expected_receiver_type_)) return depth;
+ return kInvalidProtoDepth;
+}
+
+
+void CallOptimization::Initialize(JSFunction* function) {
+ constant_function_ = NULL;
+ is_simple_api_call_ = false;
+ expected_receiver_type_ = NULL;
+ api_call_info_ = NULL;
+
+ if (function == NULL || !function->is_compiled()) return;
+
+ constant_function_ = function;
+ AnalyzePossibleApiFunction(function);
+}
+
+
+void CallOptimization::AnalyzePossibleApiFunction(JSFunction* function) {
+ SharedFunctionInfo* sfi = function->shared();
+ if (!sfi->IsApiFunction()) return;
+ FunctionTemplateInfo* info = sfi->get_api_func_data();
+
+ // Require a C++ callback.
+ if (info->call_code()->IsUndefined()) return;
+ api_call_info_ = CallHandlerInfo::cast(info->call_code());
+
+ // Accept signatures that either have no restrictions at all or
+ // only have restrictions on the receiver.
+ if (!info->signature()->IsUndefined()) {
+ SignatureInfo* signature = SignatureInfo::cast(info->signature());
+ if (!signature->args()->IsUndefined()) return;
+ if (!signature->receiver()->IsUndefined()) {
+ expected_receiver_type_ =
+ FunctionTemplateInfo::cast(signature->receiver());
+ }
+ }
+
+ is_simple_api_call_ = true;
+}
+
+
} } // namespace v8::internal