Index: test/cctest/test-api.cc |
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc |
index f71b3258a8a34afba89f1576b45870c3f7e2ddc5..3bc0cc6401310e275e7fa497fdbc57d3047f1781 100644 |
--- a/test/cctest/test-api.cc |
+++ b/test/cctest/test-api.cc |
@@ -5793,6 +5793,257 @@ THREADED_TEST(InterceptorCallICCachedFromGlobal) { |
CHECK_EQ(239 * 10, value->Int32Value()); |
} |
+static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name, |
antonm
2010/02/08 12:07:38
I know that's boring, but apparently you didn't co
Vitaly Repeshko
2010/02/09 16:15:24
Thanks, added a test. Yeah, it's boring...
|
+ const AccessorInfo& info) { |
+ ApiTestFuzzer::Fuzz(); |
+ int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data())); |
+ ++(*call_count); |
+ if ((*call_count) % 200 == 0) { |
+ v8::internal::Heap::CollectAllGarbage(true); |
+ } |
+ return v8::Handle<Value>(); |
+} |
+ |
+static v8::Handle<Value> FastApiCallback_TrivialSignature( |
+ const v8::Arguments& args) { |
+ ApiTestFuzzer::Fuzz(); |
+ CHECK_EQ(args.This(), args.Holder()); |
+ CHECK(args.Data()->Equals(v8_str("method_data"))); |
+ return v8::Integer::New(args[0]->Int32Value() + 1); |
+} |
+ |
+static v8::Handle<Value> FastApiCallback_SimpleSignature( |
+ const v8::Arguments& args) { |
+ ApiTestFuzzer::Fuzz(); |
+ CHECK_EQ(args.This()->GetPrototype(), args.Holder()); |
+ CHECK(args.Data()->Equals(v8_str("method_data"))); |
+ // Note, we're using HasRealNamedProperty instead of Has to avoid |
+ // invoking the interceptor again. |
+ CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo"))); |
+ return v8::Integer::New(args[0]->Int32Value() + 1); |
+} |
+ |
+static void GenerateSomeGarbage() { |
+ CompileRun( |
+ "var garbage;" |
+ "for (var i = 0; i < 1000; i++) {" |
+ " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];" |
+ "}" |
+ "garbage = undefined;"); |
+} |
+ |
+THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) { |
+ 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_TrivialSignature, |
+ v8_str("method_data"), |
+ v8::Handle<v8::Signature>()); |
+ 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(); |
Mads Ager (chromium)
2010/02/08 08:56:58
Could you document why you generate some extra gar
Vitaly Repeshko
2010/02/09 16:15:24
Done.
|
+ context->Global()->Set(v8_str("o"), fun->NewInstance()); |
+ v8::Handle<Value> value = CompileRun( |
+ "var result = 0;" |
+ "for (var i = 0; i < 1000; i++) {" |
Mads Ager (chromium)
2010/02/08 08:56:58
I think we use 1000 in other places as well, but d
Vitaly Repeshko
2010/02/09 16:15:24
Sure we don't need that many. Reduced iterations b
|
+ " result = o.method(41);" |
+ "}"); |
+ CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); |
antonm
2010/02/08 12:07:38
if you add result as a last line of script, you co
Vitaly Repeshko
2010/02/09 16:15:24
Yup, but I prefer a slightly more uniform way here
|
+ CHECK_EQ(1000, interceptor_call_count); |
+} |
+ |
+THREADED_TEST(InterceptorCallICFastApi_SimpleSignature) { |
+ 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::Handle<Value> value = CompileRun( |
+ "o.foo = 17;" |
+ "var receiver = {};" |
+ "receiver.__proto__ = o;" |
+ "var result = 0;" |
+ "for (var i = 0; i < 1000; i++) {" |
+ " result = receiver.method(41);" |
+ "}"); |
+ CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); |
+ CHECK_EQ(1000, interceptor_call_count); |
+} |
+ |
+THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss) { |
+ 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::Handle<Value> value = CompileRun( |
+ "o.foo = 17;" |
+ "var receiver = {};" |
+ "receiver.__proto__ = o;" |
+ "var result = 0;" |
+ "var saved_result = 0;" |
+ "for (var i = 0; i < 1000; i++) {" |
+ " result = receiver.method(41);" |
+ " if (i == 500) {" |
+ " saved_result = result;" |
+ " receiver = {method: function(x) { return x - 1 }};" |
+ " }" |
+ "}"); |
+ CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value()); |
+ CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); |
+ CHECK(interceptor_call_count >= 500); |
+} |
+ |
+THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) { |
+ 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 < 1000; i++) {" |
+ " result = receiver.method(41);" |
+ " if (i == 500) {" |
+ " saved_result = result;" |
+ " receiver = {method: receiver.method};" |
+ " }" |
+ "}"); |
+ CHECK(try_catch.HasCaught()); |
+ CHECK_EQ(v8_str("TypeError: Illegal invocation"), |
+ try_catch.Exception()->ToString()); |
+ CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); |
+ CHECK(interceptor_call_count >= 500); |
+} |
+ |
+THREADED_TEST(CallICFastApi_TrivialSignature) { |
+ v8::HandleScope scope; |
+ v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); |
+ v8::Handle<v8::FunctionTemplate> method_templ = |
+ v8::FunctionTemplate::New(FastApiCallback_TrivialSignature, |
+ v8_str("method_data"), |
+ v8::Handle<v8::Signature>()); |
+ 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::Handle<Value> value = CompileRun( |
+ "var result = 0;" |
+ "for (var i = 0; i < 1000; i++) {" |
+ " result = o.method(41);" |
+ "}"); |
+ |
+ CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); |
+} |
+ |
+THREADED_TEST(CallICFastApi_SimpleSignature) { |
+ 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::Handle<Value> value = CompileRun( |
+ "o.foo = 17;" |
+ "var receiver = {};" |
+ "receiver.__proto__ = o;" |
+ "var result = 0;" |
+ "for (var i = 0; i < 1000; i++) {" |
+ " result = receiver.method(41);" |
+ "}"); |
+ |
+ CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); |
+} |
+ |
+THREADED_TEST(CallICFastApi_SimpleSignature_Miss) { |
+ 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::Handle<Value> value = CompileRun( |
+ "o.foo = 17;" |
+ "var receiver = {};" |
+ "receiver.__proto__ = o;" |
+ "var result = 0;" |
+ "var saved_result = 0;" |
+ "for (var i = 0; i < 1000; i++) {" |
+ " result = receiver.method(41);" |
+ " if (i == 500) {" |
+ " saved_result = result;" |
+ " receiver = {method: function(x) { return x - 1 }};" |
+ " }" |
+ "}"); |
+ CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value()); |
+ CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); |
+} |
+ |
static int interceptor_call_count = 0; |