Commit 11af95d7 authored by dcarney@chromium.org's avatar dcarney@chromium.org

load ics for js api accessors

R=mstarzinger@chromium.org
BUG=

Review URL: https://codereview.chromium.org/23699002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16543 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2fdadd77
...@@ -1292,7 +1292,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( ...@@ -1292,7 +1292,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Label* success, Label* success,
Handle<ExecutableAccessorInfo> callback) { Handle<Object> callback) {
Label miss; Label miss;
Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
...@@ -1379,6 +1379,24 @@ void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { ...@@ -1379,6 +1379,24 @@ void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
} }
void BaseLoadStubCompiler::GenerateLoadCallback(
const CallOptimization& call_optimization) {
ASSERT(call_optimization.is_simple_api_call());
// Assign stack space for the call arguments.
__ sub(sp, sp, Operand((kFastApiCallArguments + 1) * kPointerSize));
int argc = 0;
int api_call_argc = argc + kFastApiCallArguments;
// Write holder to stack frame.
__ str(receiver(), MemOperand(sp, 0));
// Write receiver to stack frame.
__ str(receiver(), MemOperand(sp, api_call_argc * kPointerSize));
GenerateFastApiDirectCall(masm(), call_optimization, argc);
}
void BaseLoadStubCompiler::GenerateLoadCallback( void BaseLoadStubCompiler::GenerateLoadCallback(
Register reg, Register reg,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
......
...@@ -1261,7 +1261,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( ...@@ -1261,7 +1261,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Label* success, Label* success,
Handle<ExecutableAccessorInfo> callback) { Handle<Object> callback) {
Label miss; Label miss;
Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
...@@ -1354,6 +1354,28 @@ void BaseLoadStubCompiler::GenerateLoadField(Register reg, ...@@ -1354,6 +1354,28 @@ void BaseLoadStubCompiler::GenerateLoadField(Register reg,
} }
void BaseLoadStubCompiler::GenerateLoadCallback(
const CallOptimization& call_optimization) {
ASSERT(call_optimization.is_simple_api_call());
// Copy return value.
__ mov(scratch3(), Operand(esp, 0));
// Assign stack space for the call arguments.
__ sub(esp, Immediate((kFastApiCallArguments + 1) * kPointerSize));
// Move the return address on top of the stack.
__ mov(Operand(esp, 0), scratch3());
int argc = 0;
int api_call_argc = argc + kFastApiCallArguments;
// Write holder to stack frame.
__ mov(Operand(esp, 1 * kPointerSize), receiver());
// Write receiver to stack frame.
__ mov(Operand(esp, (api_call_argc + 1) * kPointerSize), receiver());
GenerateFastApiCall(masm(), call_optimization, argc);
}
void BaseLoadStubCompiler::GenerateLoadCallback( void BaseLoadStubCompiler::GenerateLoadCallback(
Register reg, Register reg,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
......
...@@ -1357,8 +1357,15 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup, ...@@ -1357,8 +1357,15 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
if (!getter->IsJSFunction()) break; if (!getter->IsJSFunction()) break;
if (holder->IsGlobalObject()) break; if (holder->IsGlobalObject()) break;
if (!holder->HasFastProperties()) 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()->ComputeLoadCallback(
name, receiver, holder, call_optimization);
}
return isolate()->stub_cache()->ComputeLoadViaGetter( return isolate()->stub_cache()->ComputeLoadViaGetter(
name, receiver, holder, Handle<JSFunction>::cast(getter)); name, receiver, holder, function);
} else if (receiver->IsJSArray() && } else if (receiver->IsJSArray() &&
name->Equals(isolate()->heap()->length_string())) { name->Equals(isolate()->heap()->length_string())) {
PropertyIndex lengthIndex = PropertyIndex lengthIndex =
...@@ -1544,13 +1551,29 @@ Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, ...@@ -1544,13 +1551,29 @@ Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
case CALLBACKS: { case CALLBACKS: {
Handle<Object> callback_object(lookup->GetCallbackObject(), isolate()); Handle<Object> callback_object(lookup->GetCallbackObject(), isolate());
// TODO(dcarney): Handle DeclaredAccessorInfo correctly. // TODO(dcarney): Handle DeclaredAccessorInfo correctly.
if (!callback_object->IsExecutableAccessorInfo()) break; if (callback_object->IsExecutableAccessorInfo()) {
Handle<ExecutableAccessorInfo> callback = Handle<ExecutableAccessorInfo> callback =
Handle<ExecutableAccessorInfo>::cast(callback_object); Handle<ExecutableAccessorInfo>::cast(callback_object);
if (v8::ToCData<Address>(callback->getter()) == 0) break; if (v8::ToCData<Address>(callback->getter()) == 0) break;
if (!callback->IsCompatibleReceiver(*receiver)) break; if (!callback->IsCompatibleReceiver(*receiver)) break;
return isolate()->stub_cache()->ComputeKeyedLoadCallback( return isolate()->stub_cache()->ComputeKeyedLoadCallback(
name, receiver, holder, callback); 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: case INTERCEPTOR:
ASSERT(HasInterceptorGetter(lookup->holder())); ASSERT(HasInterceptorGetter(lookup->holder()));
......
...@@ -315,6 +315,24 @@ Handle<Code> StubCache::ComputeLoadCallback( ...@@ -315,6 +315,24 @@ Handle<Code> StubCache::ComputeLoadCallback(
} }
Handle<Code> StubCache::ComputeLoadCallback(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
const CallOptimization& call_optimization) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindLoadHandler(
name, receiver, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
if (!stub.is_null()) return stub;
LoadStubCompiler compiler(isolate_);
Handle<Code> handler =
compiler.CompileLoadCallback(receiver, holder, name, call_optimization);
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
return handler;
}
Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name, Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<JSObject> holder, Handle<JSObject> holder,
...@@ -465,6 +483,24 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback( ...@@ -465,6 +483,24 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback(
} }
Handle<Code> StubCache::ComputeKeyedLoadCallback(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
const CallOptimization& call_optimization) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindLoadHandler(
name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
if (!stub.is_null()) return stub;
KeyedLoadStubCompiler compiler(isolate_);
Handle<Code> handler =
compiler.CompileLoadCallback(receiver, holder, name, call_optimization);
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
return handler;
}
Handle<Code> StubCache::ComputeStoreField(Handle<Name> name, Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
Handle<JSObject> receiver, Handle<JSObject> receiver,
LookupResult* lookup, LookupResult* lookup,
...@@ -1648,6 +1684,25 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadCallback( ...@@ -1648,6 +1684,25 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
} }
Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization) {
ASSERT(call_optimization.is_simple_api_call());
Label success;
Handle<JSFunction> callback = call_optimization.constant_function();
CallbackHandlerFrontend(
object, receiver(), holder, name, &success, callback);
__ bind(&success);
GenerateLoadCallback(call_optimization);
// Return the generated code.
return GetCode(kind(), Code::CALLBACKS, name);
}
Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor( Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor(
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
......
...@@ -48,6 +48,8 @@ namespace internal { ...@@ -48,6 +48,8 @@ namespace internal {
// invalidate the cache whenever a prototype map is changed. The stub // invalidate the cache whenever a prototype map is changed. The stub
// validates the map chain as in the mono-morphic case. // validates the map chain as in the mono-morphic case.
class CallOptimization;
class SmallMapList; class SmallMapList;
class StubCache; class StubCache;
...@@ -136,6 +138,11 @@ class StubCache { ...@@ -136,6 +138,11 @@ class StubCache {
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback); 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<Code> ComputeLoadViaGetter(Handle<Name> name,
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
...@@ -173,6 +180,12 @@ class StubCache { ...@@ -173,6 +180,12 @@ class StubCache {
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback); Handle<ExecutableAccessorInfo> callback);
Handle<Code> ComputeKeyedLoadCallback(
Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
const CallOptimization& call_optimization);
Handle<Code> ComputeKeyedLoadConstant(Handle<Name> name, Handle<Code> ComputeKeyedLoadConstant(Handle<Name> name,
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
...@@ -705,6 +718,11 @@ class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler { ...@@ -705,6 +718,11 @@ class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler {
Handle<Name> name, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback); Handle<ExecutableAccessorInfo> callback);
Handle<Code> CompileLoadCallback(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization);
Handle<Code> CompileLoadConstant(Handle<JSObject> object, Handle<Code> CompileLoadConstant(Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
...@@ -730,7 +748,7 @@ class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler { ...@@ -730,7 +748,7 @@ class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler {
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Label* success, Label* success,
Handle<ExecutableAccessorInfo> callback); Handle<Object> callback);
void NonexistentHandlerFrontend(Handle<JSObject> object, void NonexistentHandlerFrontend(Handle<JSObject> object,
Handle<JSObject> last, Handle<JSObject> last,
Handle<Name> name, Handle<Name> name,
...@@ -744,6 +762,7 @@ class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler { ...@@ -744,6 +762,7 @@ class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler {
void GenerateLoadConstant(Handle<Object> value); void GenerateLoadConstant(Handle<Object> value);
void GenerateLoadCallback(Register reg, void GenerateLoadCallback(Register reg,
Handle<ExecutableAccessorInfo> callback); Handle<ExecutableAccessorInfo> callback);
void GenerateLoadCallback(const CallOptimization& call_optimization);
void GenerateLoadInterceptor(Register holder_reg, void GenerateLoadInterceptor(Register holder_reg,
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
...@@ -1028,8 +1047,6 @@ class KeyedStoreStubCompiler: public BaseStoreStubCompiler { ...@@ -1028,8 +1047,6 @@ class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
V(ArrayCode) V(ArrayCode)
class CallOptimization;
class CallStubCompiler: public StubCompiler { class CallStubCompiler: public StubCompiler {
public: public:
CallStubCompiler(Isolate* isolate, CallStubCompiler(Isolate* isolate,
...@@ -1161,6 +1178,12 @@ class CallOptimization BASE_EMBEDDED { ...@@ -1161,6 +1178,12 @@ class CallOptimization BASE_EMBEDDED {
int GetPrototypeDepthOfExpectedType(Handle<JSObject> object, int GetPrototypeDepthOfExpectedType(Handle<JSObject> object,
Handle<JSObject> holder) const; Handle<JSObject> holder) const;
bool IsCompatibleReceiver(Object* receiver) {
ASSERT(is_simple_api_call());
if (expected_receiver_type_.is_null()) return true;
return receiver->IsInstanceOf(*expected_receiver_type_);
}
private: private:
void Initialize(Handle<JSFunction> function); void Initialize(Handle<JSFunction> function);
......
...@@ -1191,7 +1191,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( ...@@ -1191,7 +1191,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Label* success, Label* success,
Handle<ExecutableAccessorInfo> callback) { Handle<Object> callback) {
Label miss; Label miss;
Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
...@@ -1275,6 +1275,29 @@ void BaseLoadStubCompiler::GenerateLoadField(Register reg, ...@@ -1275,6 +1275,29 @@ void BaseLoadStubCompiler::GenerateLoadField(Register reg,
} }
void BaseLoadStubCompiler::GenerateLoadCallback(
const CallOptimization& call_optimization) {
ASSERT(call_optimization.is_simple_api_call());
// Copy return value.
__ movq(scratch3(), StackSpaceOperand(0));
// Assign stack space for the call arguments.
__ subq(rsp, Immediate((kFastApiCallArguments + 1) * kPointerSize));
// Move the return address on top of the stack.
__ movq(StackOperandForReturnAddress(0), scratch3());
int argc = 0;
int api_call_argc = argc + kFastApiCallArguments;
StackArgumentsAccessor args(rsp, api_call_argc);
// Write holder to stack frame.
__ movq(args.GetArgumentOperand(api_call_argc), receiver());
// Write receiver to stack frame.
__ movq(args.GetArgumentOperand(api_call_argc - (argc + 6)), receiver());
GenerateFastApiCall(masm(), call_optimization, argc);
}
void BaseLoadStubCompiler::GenerateLoadCallback( void BaseLoadStubCompiler::GenerateLoadCallback(
Register reg, Register reg,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
......
...@@ -163,6 +163,7 @@ static void XGetter(Local<String> name, ...@@ -163,6 +163,7 @@ static void XGetter(Local<String> name,
static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
CHECK_EQ(x_receiver, info.Holder());
XGetter(info, 1); XGetter(info, 1);
} }
...@@ -172,6 +173,7 @@ static void XSetter(Local<Value> value, const Info& info, int offset) { ...@@ -172,6 +173,7 @@ static void XSetter(Local<Value> value, const Info& info, int offset) {
v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Isolate* isolate = v8::Isolate::GetCurrent();
CHECK_EQ(isolate, info.GetIsolate()); CHECK_EQ(isolate, info.GetIsolate());
CHECK_EQ(x_holder, info.This()); CHECK_EQ(x_holder, info.This());
CHECK_EQ(x_holder, info.Holder());
x_register[offset] = value->Int32Value(); x_register[offset] = value->Int32Value();
} }
...@@ -179,7 +181,6 @@ static void XSetter(Local<Value> value, const Info& info, int offset) { ...@@ -179,7 +181,6 @@ static void XSetter(Local<Value> value, const Info& info, int offset) {
static void XSetter(Local<String> name, static void XSetter(Local<String> name,
Local<Value> value, Local<Value> value,
const v8::PropertyCallbackInfo<void>& info) { const v8::PropertyCallbackInfo<void>& info) {
CHECK_EQ(x_holder, info.Holder());
XSetter(value, info, 0); XSetter(value, info, 0);
} }
...@@ -205,17 +206,23 @@ THREADED_TEST(AccessorIC) { ...@@ -205,17 +206,23 @@ THREADED_TEST(AccessorIC) {
v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun( v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun(
"obj.__proto__ = holder;" "obj.__proto__ = holder;"
"var result = [];" "var result = [];"
"var key_0 = 'x0';"
"var key_1 = 'x1';"
"for (var i = 0; i < 10; i++) {" "for (var i = 0; i < 10; i++) {"
" holder.x0 = i;" " holder.x0 = i;"
" holder.x1 = i;"
" result.push(obj.x0);" " result.push(obj.x0);"
" holder.x1 = i;"
" result.push(obj.x1);" " result.push(obj.x1);"
" holder[key_0] = i;"
" result.push(obj[key_0]);"
" holder[key_1] = i;"
" result.push(obj[key_1]);"
"}" "}"
"result")); "result"));
CHECK_EQ(20, array->Length()); CHECK_EQ(40, array->Length());
for (int i = 0; i < 20; i++) { for (int i = 0; i < 40; i++) {
v8::Handle<Value> entry = array->Get(v8::Integer::New(i)); v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
CHECK_EQ(v8::Integer::New(i/2), entry); CHECK_EQ(v8::Integer::New(i/4), entry);
} }
} }
......
...@@ -141,10 +141,13 @@ static void ExpectUndefined(const char* code) { ...@@ -141,10 +141,13 @@ static void ExpectUndefined(const char* code) {
static int signature_callback_count; static int signature_callback_count;
static Local<Value> signature_expected_receiver;
static void IncrementingSignatureCallback( static void IncrementingSignatureCallback(
const v8::FunctionCallbackInfo<v8::Value>& args) { const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz(); ApiTestFuzzer::Fuzz();
signature_callback_count++; signature_callback_count++;
CHECK_EQ(signature_expected_receiver, args.Holder());
CHECK_EQ(signature_expected_receiver, args.This());
v8::Handle<v8::Array> result = v8::Array::New(args.Length()); v8::Handle<v8::Array> result = v8::Array::New(args.Length());
for (int i = 0; i < args.Length(); i++) for (int i = 0; i < args.Length(); i++)
result->Set(v8::Integer::New(i), args[i]); result->Set(v8::Integer::New(i), args[i]);
...@@ -213,26 +216,50 @@ THREADED_TEST(ReceiverSignature) { ...@@ -213,26 +216,50 @@ THREADED_TEST(ReceiverSignature) {
v8::FunctionTemplate::New(IncrementingSignatureCallback, v8::FunctionTemplate::New(IncrementingSignatureCallback,
v8::Handle<Value>(), v8::Handle<Value>(),
sig)); sig));
fun->PrototypeTemplate()->SetAccessorProperty(
v8_str("n"),
v8::FunctionTemplate::New(IncrementingSignatureCallback,
v8::Handle<Value>(),
sig));
env->Global()->Set(v8_str("Fun"), fun->GetFunction()); env->Global()->Set(v8_str("Fun"), fun->GetFunction());
Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
env->Global()->Set(v8_str("fun_instance"), fun_instance);
signature_callback_count = 0; signature_callback_count = 0;
int expected_count = 0;
signature_expected_receiver = fun_instance;
CompileRun( CompileRun(
"var o = new Fun();" "var o = fun_instance;"
"o.m();"); "var key_n = 'n';"
CHECK_EQ(1, signature_callback_count); "for (var i = 0; i < 10; i++) o.m();"
"for (var i = 0; i < 10; i++) o.n;"
"for (var i = 0; i < 10; i++) o[key_n];");
expected_count += 30;
CHECK_EQ(expected_count, signature_callback_count);
v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(); v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
sub_fun->Inherit(fun); sub_fun->Inherit(fun);
env->Global()->Set(v8_str("SubFun"), sub_fun->GetFunction()); fun_instance = sub_fun->InstanceTemplate()->NewInstance();
env->Global()->Set(v8_str("fun_instance"), fun_instance);
signature_expected_receiver = fun_instance;
CompileRun( CompileRun(
"var o = new SubFun();" "var o = fun_instance;"
"o.m();"); "var key_n = 'n';"
CHECK_EQ(2, signature_callback_count); "for (var i = 0; i < 10; i++) o.m();"
"for (var i = 0; i < 10; i++) o.n;"
"for (var i = 0; i < 10; i++) o[key_n];");
expected_count += 30;
CHECK_EQ(expected_count, signature_callback_count);
v8::TryCatch try_catch; v8::TryCatch try_catch;
CompileRun( CompileRun(
"var o = { };" "var o = { };"
"o.m = Fun.prototype.m;" "o.m = Fun.prototype.m;"
"o.m();"); "o.m();");
CHECK_EQ(2, signature_callback_count); CHECK_EQ(expected_count, signature_callback_count);
CHECK(try_catch.HasCaught());
CompileRun(
"var o = { };"
"o.n = Fun.prototype.n;"
"o.n;");
CHECK_EQ(expected_count, signature_callback_count);
CHECK(try_catch.HasCaught()); CHECK(try_catch.HasCaught());
try_catch.Reset(); try_catch.Reset();
v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New(); v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
...@@ -242,7 +269,14 @@ THREADED_TEST(ReceiverSignature) { ...@@ -242,7 +269,14 @@ THREADED_TEST(ReceiverSignature) {
"var o = new UnrelFun();" "var o = new UnrelFun();"
"o.m = Fun.prototype.m;" "o.m = Fun.prototype.m;"
"o.m();"); "o.m();");
CHECK_EQ(2, signature_callback_count); CHECK_EQ(expected_count, signature_callback_count);
CHECK(try_catch.HasCaught());
try_catch.Reset();
CompileRun(
"var o = new UnrelFun();"
"o.n = Fun.prototype.n;"
"o.n;");
CHECK_EQ(expected_count, signature_callback_count);
CHECK(try_catch.HasCaught()); CHECK(try_catch.HasCaught());
} }
......
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