Fix miss in smi check when doing fast api call.

BUG=http://crbug.com/36604

Review URL: http://codereview.chromium.org/660004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3942 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
vitalyr@chromium.org 2010-02-24 19:26:10 +00:00
parent 3d76502914
commit e76f06a1e2
2 changed files with 78 additions and 3 deletions

View File

@ -1223,7 +1223,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
Label miss;
Label miss_in_smi_check;
// Get the receiver from the stack.
const int argc = arguments().immediate();
@ -1232,7 +1232,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
// Check that the receiver isn't a smi.
if (check != NUMBER_CHECK) {
__ test(edx, Immediate(kSmiTagMask));
__ j(zero, &miss, not_taken);
__ j(zero, &miss_in_smi_check, not_taken);
}
// Make sure that it's okay not to patch the on stack receiver
@ -1241,6 +1241,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
CallOptimization optimization(function);
int depth = kInvalidProtoDepth;
Label miss;
switch (check) {
case RECEIVER_MAP_CHECK:
@ -1359,6 +1360,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
if (depth != kInvalidProtoDepth) {
FreeSpaceForFastApiCall(masm(), eax);
}
__ bind(&miss_in_smi_check);
Handle<Code> ic = ComputeCallMiss(arguments().immediate());
__ jmp(ic, RelocInfo::CODE_TARGET);

View File

@ -6433,6 +6433,45 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
CHECK_GE(interceptor_call_count, 50);
}
THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
int interceptor_call_count = 0;
v8::HandleScope scope;
v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
v8::Handle<v8::FunctionTemplate> method_templ =
v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
v8_str("method_data"),
v8::Signature::New(fun_templ));
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
NULL, NULL, NULL, NULL,
v8::External::Wrap(&interceptor_call_count));
LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch;
v8::Handle<Value> value = CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
"var result = 0;"
"var saved_result = 0;"
"for (var i = 0; i < 100; i++) {"
" result = receiver.method(41);"
" if (i == 50) {"
" saved_result = result;"
" receiver = 333;"
" }"
"}");
CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
try_catch.Exception()->ToString());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
CHECK_GE(interceptor_call_count, 50);
}
THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
int interceptor_call_count = 0;
v8::HandleScope scope;
@ -6521,7 +6560,7 @@ THREADED_TEST(CallICFastApi_SimpleSignature) {
CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
}
THREADED_TEST(CallICFastApi_SimpleSignature_Miss) {
THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) {
v8::HandleScope scope;
v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
v8::Handle<v8::FunctionTemplate> method_templ =
@ -6552,6 +6591,40 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss) {
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
}
THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) {
v8::HandleScope scope;
v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
v8::Handle<v8::FunctionTemplate> method_templ =
v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
v8_str("method_data"),
v8::Signature::New(fun_templ));
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch;
v8::Handle<Value> value = CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
"var result = 0;"
"var saved_result = 0;"
"for (var i = 0; i < 100; i++) {"
" result = receiver.method(41);"
" if (i == 50) {"
" saved_result = result;"
" receiver = 333;"
" }"
"}");
CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
try_catch.Exception()->ToString());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
}
static int interceptor_call_count = 0;