Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(940)

Side by Side Diff: test/cctest/test-api.cc

Issue 149749: Some more test for load and call stubs. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2007-2008 the V8 project authors. All rights reserved. 1 // Copyright 2007-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 5006 matching lines...) Expand 10 before | Expand all | Expand 10 after
5017 "fst.x = 239;" 5017 "fst.x = 239;"
5018 "var result = 0;" 5018 "var result = 0;"
5019 "for (var i = 0; i < 1000; i++) {" 5019 "for (var i = 0; i < 1000; i++) {"
5020 " result = snd.x;" 5020 " result = snd.x;"
5021 "}" 5021 "}"
5022 "result + result1", 5022 "result + result1",
5023 239 + 42); 5023 239 + 42);
5024 } 5024 }
5025 5025
5026 5026
5027 // Test the case when we stored field into
5028 // a stub, but interceptor produced value on its own.
5029 THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
5030 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
5031 "proto = new Object();"
5032 "o.__proto__ = proto;"
5033 "proto.x = 239;"
5034 "for (var i = 0; i < 1000; i++) {"
5035 " o.x;"
5036 // Now it should be ICed and keep a reference to x defined on proto
5037 "}"
5038 "var result = 0;"
5039 "for (var i = 0; i < 1000; i++) {"
5040 " result += o.x;"
5041 "}"
5042 "result;",
5043 42 * 1000);
5044 }
5045
5046
5047 // Test the case when we stored field into
5048 // a stub, but it got invalidated later on.
5049 THREADED_TEST(InterceptorLoadICInvalidatedField) {
5050 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
5051 "proto1 = new Object();"
5052 "proto2 = new Object();"
5053 "o.__proto__ = proto1;"
5054 "proto1.__proto__ = proto2;"
5055 "proto2.y = 239;"
5056 "for (var i = 0; i < 1000; i++) {"
5057 " o.y;"
5058 // Now it should be ICed and keep a reference to y defined on proto2
5059 "}"
5060 "proto1.y = 42;"
5061 "var result = 0;"
5062 "for (var i = 0; i < 1000; i++) {"
5063 " result += o.y;"
5064 "}"
5065 "result;",
5066 42 * 1000);
5067 }
5068
5069
5070 // Test the case when we stored field into
5071 // a stub, but it got invalidated later on due to override on
5072 // global object which is between interceptor and fields' holders.
5073 THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
5074 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
5075 "o.__proto__ = this;" // set a global to be a proto of o.
5076 "this.__proto__.y = 239;"
5077 "for (var i = 0; i < 10; i++) {"
5078 " if (o.y != 239) throw 'oops: ' + o.y;"
5079 // Now it should be ICed and keep a reference to y defined on field_holder.
5080 "}"
5081 "this.y = 42;" // Assign on a global.
5082 "var result = 0;"
5083 "for (var i = 0; i < 10; i++) {"
5084 " result += o.y;"
5085 "}"
5086 "result;",
5087 42 * 10);
5088 }
5089
5090
5091 static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) {
5092 ApiTestFuzzer::Fuzz();
5093 return v8_num(239);
5094 }
5095
5096
5097 static void SetOnThis(Local<String> name,
5098 Local<Value> value,
5099 const AccessorInfo& info) {
5100 info.This()->ForceSet(name, value);
5101 }
5102
5103
5104 THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
5105 v8::HandleScope scope;
5106 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
5107 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
5108 templ->SetAccessor(v8_str("y"), Return239);
5109 LocalContext context;
5110 context->Global()->Set(v8_str("o"), templ->NewInstance());
5111 v8::Handle<Value> value = CompileRun(
5112 "var result = 0;"
5113 "for (var i = 0; i < 7; i++) {"
5114 " result = o.y;"
5115 "}");
5116 CHECK_EQ(239, value->Int32Value());
5117 }
5118
5119
5120 THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
5121 v8::HandleScope scope;
5122 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
5123 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
5124 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
5125 templ_p->SetAccessor(v8_str("y"), Return239);
5126
5127 LocalContext context;
5128 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
5129 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
5130
5131 v8::Handle<Value> value = CompileRun(
5132 "o.__proto__ = p;"
5133 "var result = 0;"
5134 "for (var i = 0; i < 7; i++) {"
5135 " result = o.x + o.y;"
5136 "}");
5137 CHECK_EQ(239 + 42, value->Int32Value());
5138 }
5139
5140
5141 THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
5142 v8::HandleScope scope;
5143 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
5144 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
5145 templ->SetAccessor(v8_str("y"), Return239);
5146
5147 LocalContext context;
5148 context->Global()->Set(v8_str("o"), templ->NewInstance());
5149
5150 v8::Handle<Value> value = CompileRun(
5151 "fst = new Object(); fst.__proto__ = o;"
5152 "snd = new Object(); snd.__proto__ = fst;"
5153 "var result1 = 0;"
5154 "for (var i = 0; i < 7; i++) {"
5155 " result1 = snd.x;"
5156 "}"
5157 "fst.x = 239;"
5158 "var result = 0;"
5159 "for (var i = 0; i < 7; i++) {"
5160 " result = snd.x;"
5161 "}"
5162 "result + result1");
5163 CHECK_EQ(239 + 42, value->Int32Value());
5164 }
5165
5166
5167 // Test the case when we stored callback into
5168 // a stub, but interceptor produced value on its own.
5169 THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
5170 v8::HandleScope scope;
5171 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
5172 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
5173 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
5174 templ_p->SetAccessor(v8_str("y"), Return239);
5175
5176 LocalContext context;
5177 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
5178 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
5179
5180 v8::Handle<Value> value = CompileRun(
5181 "o.__proto__ = p;"
5182 "for (var i = 0; i < 7; i++) {"
5183 " o.x;"
5184 // Now it should be ICed and keep a reference to x defined on p
5185 "}"
5186 "var result = 0;"
5187 "for (var i = 0; i < 7; i++) {"
5188 " result += o.x;"
5189 "}"
5190 "result");
5191 CHECK_EQ(42 * 7, value->Int32Value());
5192 }
5193
5194
5195 // Test the case when we stored callback into
5196 // a stub, but it got invalidated later on.
5197 THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
5198 v8::HandleScope scope;
5199 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
5200 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
5201 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
5202 templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
5203
5204 LocalContext context;
5205 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
5206 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
5207
5208 v8::Handle<Value> value = CompileRun(
5209 "inbetween = new Object();"
5210 "o.__proto__ = inbetween;"
5211 "inbetween.__proto__ = p;"
5212 "for (var i = 0; i < 10; i++) {"
5213 " o.y;"
5214 // Now it should be ICed and keep a reference to y defined on p
5215 "}"
5216 "inbetween.y = 42;"
5217 "var result = 0;"
5218 "for (var i = 0; i < 10; i++) {"
5219 " result += o.y;"
5220 "}"
5221 "result");
5222 CHECK_EQ(42 * 10, value->Int32Value());
5223 }
5224
5225
5226 // Test the case when we stored callback into
5227 // a stub, but it got invalidated later on due to override on
5228 // global object which is between interceptor and callbacks' holders.
5229 THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
5230 v8::HandleScope scope;
5231 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
5232 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
5233 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
5234 templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
5235
5236 LocalContext context;
5237 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
5238 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
5239
5240 v8::Handle<Value> value = CompileRun(
5241 "o.__proto__ = this;"
5242 "this.__proto__ = p;"
5243 "for (var i = 0; i < 10; i++) {"
5244 " if (o.y != 239) throw 'oops: ' + o.y;"
5245 // Now it should be ICed and keep a reference to y defined on p
5246 "}"
5247 "this.y = 42;"
5248 "var result = 0;"
5249 "for (var i = 0; i < 10; i++) {"
5250 " result += o.y;"
5251 "}"
5252 "result");
5253 CHECK_EQ(42 * 10, value->Int32Value());
5254 }
5255
5256
5027 static v8::Handle<Value> InterceptorLoadICGetter0(Local<String> name, 5257 static v8::Handle<Value> InterceptorLoadICGetter0(Local<String> name,
5028 const AccessorInfo& info) { 5258 const AccessorInfo& info) {
5029 ApiTestFuzzer::Fuzz(); 5259 ApiTestFuzzer::Fuzz();
5030 CHECK(v8_str("x")->Equals(name)); 5260 CHECK(v8_str("x")->Equals(name));
5031 return v8::Integer::New(0); 5261 return v8::Integer::New(0);
5032 } 5262 }
5033 5263
5034 5264
5035 THREADED_TEST(InterceptorReturningZero) { 5265 THREADED_TEST(InterceptorReturningZero) {
5036 CheckInterceptorLoadIC(InterceptorLoadICGetter0, 5266 CheckInterceptorLoadIC(InterceptorLoadICGetter0,
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
5101 call_ic_function = 5331 call_ic_function =
5102 v8_compile("function f(x) { return x + 1; }; f")->Run(); 5332 v8_compile("function f(x) { return x + 1; }; f")->Run();
5103 v8::Handle<Value> value = CompileRun( 5333 v8::Handle<Value> value = CompileRun(
5104 "var result = 0;" 5334 "var result = 0;"
5105 "for (var i = 0; i < 1000; i++) {" 5335 "for (var i = 0; i < 1000; i++) {"
5106 " result = o.x(41);" 5336 " result = o.x(41);"
5107 "}"); 5337 "}");
5108 CHECK_EQ(42, value->Int32Value()); 5338 CHECK_EQ(42, value->Int32Value());
5109 } 5339 }
5110 5340
5341
5342 // This test checks that if interceptor doesn't provide
5343 // a value, we can fetch regular value.
5344 THREADED_TEST(InterceptorCallICSeesOthers) {
5345 v8::HandleScope scope;
5346 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
5347 templ->SetNamedPropertyHandler(NoBlockGetterX);
5348 LocalContext context;
5349 context->Global()->Set(v8_str("o"), templ->NewInstance());
5350 v8::Handle<Value> value = CompileRun(
5351 "o.x = function f(x) { return x + 1; };"
5352 "var result = 0;"
5353 "for (var i = 0; i < 7; i++) {"
5354 " result = o.x(41);"
5355 "}");
5356 CHECK_EQ(42, value->Int32Value());
5357 }
5358
5359
5360 static v8::Handle<Value> call_ic_function4;
5361 static v8::Handle<Value> InterceptorCallICGetter4(Local<String> name,
5362 const AccessorInfo& info) {
5363 ApiTestFuzzer::Fuzz();
5364 CHECK(v8_str("x")->Equals(name));
5365 return call_ic_function4;
5366 }
5367
5368
5369 // This test checks that if interceptor provides a function,
5370 // even if we cached shadowed variant, interceptor's function
5371 // is invoked
5372 THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
5373 v8::HandleScope scope;
5374 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
5375 templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
5376 LocalContext context;
5377 context->Global()->Set(v8_str("o"), templ->NewInstance());
5378 call_ic_function4 =
5379 v8_compile("function f(x) { return x - 1; }; f")->Run();
5380 v8::Handle<Value> value = CompileRun(
5381 "o.__proto__.x = function(x) { return x + 1; };"
5382 "var result = 0;"
5383 "for (var i = 0; i < 1000; i++) {"
5384 " result = o.x(42);"
5385 "}");
5386 CHECK_EQ(41, value->Int32Value());
5387 }
5388
5389
5390 // Test the case when we stored cacheable lookup into
5391 // a stub, but it got invalidated later on
5392 THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
5393 v8::HandleScope scope;
5394 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
5395 templ->SetNamedPropertyHandler(NoBlockGetterX);
5396 LocalContext context;
5397 context->Global()->Set(v8_str("o"), templ->NewInstance());
5398 v8::Handle<Value> value = CompileRun(
5399 "proto1 = new Object();"
5400 "proto2 = new Object();"
5401 "o.__proto__ = proto1;"
5402 "proto1.__proto__ = proto2;"
5403 "proto2.y = function(x) { return x + 1; };"
5404 // Invoke it many times to compile a stub
5405 "for (var i = 0; i < 7; i++) {"
5406 " o.y(42);"
5407 "}"
5408 "proto1.y = function(x) { return x - 1; };"
5409 "var result = 0;"
5410 "for (var i = 0; i < 7; i++) {"
5411 " result += o.y(42);"
5412 "}");
5413 CHECK_EQ(41 * 7, value->Int32Value());
5414 }
5415
5416
5417 static v8::Handle<Value> call_ic_function5;
5418 static v8::Handle<Value> InterceptorCallICGetter5(Local<String> name,
5419 const AccessorInfo& info) {
5420 ApiTestFuzzer::Fuzz();
5421 if (v8_str("x")->Equals(name))
5422 return call_ic_function5;
5423 else
5424 return Local<Value>();
5425 }
5426
5427
5428 // This test checks that if interceptor doesn't provide a function,
5429 // cached constant function is used
5430 THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
5431 v8::HandleScope scope;
5432 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
5433 templ->SetNamedPropertyHandler(NoBlockGetterX);
5434 LocalContext context;
5435 context->Global()->Set(v8_str("o"), templ->NewInstance());
5436 v8::Handle<Value> value = CompileRun(
5437 "function inc(x) { return x + 1; };"
5438 "inc(1);"
5439 "o.x = inc;"
5440 "var result = 0;"
5441 "for (var i = 0; i < 1000; i++) {"
5442 " result = o.x(42);"
5443 "}");
5444 CHECK_EQ(43, value->Int32Value());
5445 }
5446
5447
5448 // This test checks that if interceptor provides a function,
5449 // even if we cached constant function, interceptor's function
5450 // is invoked
5451 THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
5452 v8::HandleScope scope;
5453 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
5454 templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
5455 LocalContext context;
5456 context->Global()->Set(v8_str("o"), templ->NewInstance());
5457 call_ic_function5 =
5458 v8_compile("function f(x) { return x - 1; }; f")->Run();
5459 v8::Handle<Value> value = CompileRun(
5460 "function inc(x) { return x + 1; };"
5461 "inc(1);"
5462 "o.x = inc;"
5463 "var result = 0;"
5464 "for (var i = 0; i < 1000; i++) {"
5465 " result = o.x(42);"
5466 "}");
5467 CHECK_EQ(41, value->Int32Value());
5468 }
5469
5470
5471 // Test the case when we stored constant function into
5472 // a stub, but it got invalidated later on
5473 THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
5474 v8::HandleScope scope;
5475 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
5476 templ->SetNamedPropertyHandler(NoBlockGetterX);
5477 LocalContext context;
5478 context->Global()->Set(v8_str("o"), templ->NewInstance());
5479 v8::Handle<Value> value = CompileRun(
5480 "function inc(x) { return x + 1; };"
5481 "inc(1);"
5482 "proto1 = new Object();"
5483 "proto2 = new Object();"
5484 "o.__proto__ = proto1;"
5485 "proto1.__proto__ = proto2;"
5486 "proto2.y = inc;"
5487 // Invoke it many times to compile a stub
5488 "for (var i = 0; i < 7; i++) {"
5489 " o.y(42);"
5490 "}"
5491 "proto1.y = function(x) { return x - 1; };"
5492 "var result = 0;"
5493 "for (var i = 0; i < 7; i++) {"
5494 " result += o.y(42);"
5495 "}");
5496 CHECK_EQ(41 * 7, value->Int32Value());
5497 }
5498
5499
5500 // Test the case when we stored constant function into
5501 // a stub, but it got invalidated later on due to override on
5502 // global object which is between interceptor and constant function' holders.
5503 THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
5504 v8::HandleScope scope;
5505 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
5506 templ->SetNamedPropertyHandler(NoBlockGetterX);
5507 LocalContext context;
5508 context->Global()->Set(v8_str("o"), templ->NewInstance());
5509 v8::Handle<Value> value = CompileRun(
5510 "function inc(x) { return x + 1; };"
5511 "inc(1);"
5512 "o.__proto__ = this;"
5513 "this.__proto__.y = inc;"
5514 // Invoke it many times to compile a stub
5515 "for (var i = 0; i < 7; i++) {"
5516 " if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
5517 "}"
5518 "this.y = function(x) { return x - 1; };"
5519 "var result = 0;"
5520 "for (var i = 0; i < 7; i++) {"
5521 " result += o.y(42);"
5522 "}");
5523 CHECK_EQ(41 * 7, value->Int32Value());
5524 }
5525
5526
5111 static int interceptor_call_count = 0; 5527 static int interceptor_call_count = 0;
5112 5528
5113 static v8::Handle<Value> InterceptorICRefErrorGetter(Local<String> name, 5529 static v8::Handle<Value> InterceptorICRefErrorGetter(Local<String> name,
5114 const AccessorInfo& info) { 5530 const AccessorInfo& info) {
5115 ApiTestFuzzer::Fuzz(); 5531 ApiTestFuzzer::Fuzz();
5116 if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) { 5532 if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
5117 return call_ic_function2; 5533 return call_ic_function2;
5118 } 5534 }
5119 return v8::Handle<Value>(); 5535 return v8::Handle<Value>();
5120 } 5536 }
(...skipping 1971 matching lines...) Expand 10 before | Expand all | Expand 10 after
7092 "var obj = { x: { foo: 42 }, y: 87 };\n" 7508 "var obj = { x: { foo: 42 }, y: 87 };\n"
7093 "var x = obj.x;\n" 7509 "var x = obj.x;\n"
7094 "delete obj.y;\n" 7510 "delete obj.y;\n"
7095 "for (var i = 0; i < 5; i++) f(obj);"); 7511 "for (var i = 0; i < 5; i++) f(obj);");
7096 // Detach the global object to make 'this' refer directly to the 7512 // Detach the global object to make 'this' refer directly to the
7097 // global object (not the proxy), and make sure that the dictionary 7513 // global object (not the proxy), and make sure that the dictionary
7098 // load IC doesn't mess up loading directly from the global object. 7514 // load IC doesn't mess up loading directly from the global object.
7099 context->DetachGlobal(); 7515 context->DetachGlobal();
7100 CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value()); 7516 CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value());
7101 } 7517 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698