OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 i::FLAG_allow_natives_syntax = true; | 291 i::FLAG_allow_natives_syntax = true; |
292 CcTest::InitializeVM(); | 292 CcTest::InitializeVM(); |
293 if (!CcTest::i_isolate()->use_crankshaft()) return; | 293 if (!CcTest::i_isolate()->use_crankshaft()) return; |
294 v8::HandleScope scope(CcTest::isolate()); | 294 v8::HandleScope scope(CcTest::isolate()); |
295 | 295 |
296 // Make sure function f has a call that uses a type feedback slot. | 296 // Make sure function f has a call that uses a type feedback slot. |
297 CompileRun("function fun() {};" | 297 CompileRun("function fun() {};" |
298 "fun1 = fun;" | 298 "fun1 = fun;" |
299 "function f(a) { a(); } f(fun1);"); | 299 "function f(a) { a(); } f(fun1);"); |
300 | 300 |
301 Handle<JSFunction> f = | 301 Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle( |
302 v8::Utils::OpenHandle( | 302 *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))))); |
303 *v8::Handle<v8::Function>::Cast( | |
304 CcTest::global()->Get(v8_str("f")))); | |
305 | 303 |
306 // We shouldn't have deoptimization support. We want to recompile and | 304 // We shouldn't have deoptimization support. We want to recompile and |
307 // verify that our feedback vector preserves information. | 305 // verify that our feedback vector preserves information. |
308 CHECK(!f->shared()->has_deoptimization_support()); | 306 CHECK(!f->shared()->has_deoptimization_support()); |
309 Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector()); | 307 Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector()); |
310 | 308 |
311 // Verify that we gathered feedback. | 309 // Verify that we gathered feedback. |
312 CHECK(!feedback_vector->is_empty()); | 310 CHECK(!feedback_vector->is_empty()); |
313 FeedbackVectorSlot slot_for_a(0); | 311 FeedbackVectorSlot slot_for_a(0); |
314 Object* object = feedback_vector->Get(slot_for_a); | 312 Object* object = feedback_vector->Get(slot_for_a); |
(...skipping 22 matching lines...) Expand all Loading... |
337 " return (function() {" | 335 " return (function() {" |
338 " eval('');" | 336 " eval('');" |
339 " return function() {" | 337 " return function() {" |
340 " 'use strict';" | 338 " 'use strict';" |
341 " call_target();" | 339 " call_target();" |
342 " }" | 340 " }" |
343 " })();" | 341 " })();" |
344 "}" | 342 "}" |
345 "morphing_call = builder();"); | 343 "morphing_call = builder();"); |
346 | 344 |
347 Handle<JSFunction> f = | 345 Handle<JSFunction> f = Handle<JSFunction>::cast( |
348 v8::Utils::OpenHandle( | 346 v8::Utils::OpenHandle(*v8::Handle<v8::Function>::Cast( |
349 *v8::Handle<v8::Function>::Cast( | 347 CcTest::global()->Get(v8_str("morphing_call"))))); |
350 CcTest::global()->Get(v8_str("morphing_call")))); | |
351 | 348 |
352 // Not compiled, and so no feedback vector allocated yet. | 349 // Not compiled, and so no feedback vector allocated yet. |
353 CHECK(!f->shared()->is_compiled()); | 350 CHECK(!f->shared()->is_compiled()); |
354 CHECK(f->shared()->feedback_vector()->is_empty()); | 351 CHECK(f->shared()->feedback_vector()->is_empty()); |
355 | 352 |
356 CompileRun("morphing_call();"); | 353 CompileRun("morphing_call();"); |
357 | 354 |
358 // Now a feedback vector is allocated. | 355 // Now a feedback vector is allocated. |
359 CHECK(f->shared()->is_compiled()); | 356 CHECK(f->shared()->is_compiled()); |
360 CHECK(!f->shared()->feedback_vector()->is_empty()); | 357 CHECK(!f->shared()->feedback_vector()->is_empty()); |
(...skipping 14 matching lines...) Expand all Loading... |
375 CompileRun( | 372 CompileRun( |
376 "function MakeClosure() {" | 373 "function MakeClosure() {" |
377 " return function() { return x; };" | 374 " return function() { return x; };" |
378 "}" | 375 "}" |
379 "var closure0 = MakeClosure();" | 376 "var closure0 = MakeClosure();" |
380 "%DebugPrint(closure0());" | 377 "%DebugPrint(closure0());" |
381 "%OptimizeFunctionOnNextCall(closure0);" | 378 "%OptimizeFunctionOnNextCall(closure0);" |
382 "%DebugPrint(closure0());" | 379 "%DebugPrint(closure0());" |
383 "var closure1 = MakeClosure();" | 380 "var closure1 = MakeClosure();" |
384 "var closure2 = MakeClosure();"); | 381 "var closure2 = MakeClosure();"); |
385 Handle<JSFunction> fun1 = v8::Utils::OpenHandle( | 382 Handle<JSFunction> fun1 = Handle<JSFunction>::cast( |
386 *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure1")))); | 383 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
387 Handle<JSFunction> fun2 = v8::Utils::OpenHandle( | 384 env->Global()->Get(v8_str("closure1"))))); |
388 *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure2")))); | 385 Handle<JSFunction> fun2 = Handle<JSFunction>::cast( |
| 386 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 387 env->Global()->Get(v8_str("closure2"))))); |
389 CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); | 388 CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
390 CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); | 389 CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
391 CHECK_EQ(fun1->code(), fun2->code()); | 390 CHECK_EQ(fun1->code(), fun2->code()); |
392 } | 391 } |
393 } | 392 } |
394 | 393 |
395 | 394 |
396 // Test that optimized code for different closures is actually shared | 395 // Test that optimized code for different closures is actually shared |
397 // immediately by the FastNewClosureStub when run different contexts. | 396 // immediately by the FastNewClosureStub when run different contexts. |
398 TEST(OptimizedCodeSharing2) { | 397 TEST(OptimizedCodeSharing2) { |
(...skipping 13 matching lines...) Expand all Loading... |
412 { | 411 { |
413 LocalContext env; | 412 LocalContext env; |
414 env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"), | 413 env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"), |
415 v8::Integer::New(CcTest::isolate(), 23)); | 414 v8::Integer::New(CcTest::isolate(), 23)); |
416 script->GetUnboundScript()->BindToCurrentContext()->Run(); | 415 script->GetUnboundScript()->BindToCurrentContext()->Run(); |
417 CompileRun( | 416 CompileRun( |
418 "var closure0 = MakeClosure();" | 417 "var closure0 = MakeClosure();" |
419 "%DebugPrint(closure0());" | 418 "%DebugPrint(closure0());" |
420 "%OptimizeFunctionOnNextCall(closure0);" | 419 "%OptimizeFunctionOnNextCall(closure0);" |
421 "%DebugPrint(closure0());"); | 420 "%DebugPrint(closure0());"); |
422 Handle<JSFunction> fun0 = v8::Utils::OpenHandle( | 421 Handle<JSFunction> fun0 = Handle<JSFunction>::cast( |
423 *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure0")))); | 422 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 423 env->Global()->Get(v8_str("closure0"))))); |
424 CHECK(fun0->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); | 424 CHECK(fun0->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
425 reference_code = handle(fun0->code()); | 425 reference_code = handle(fun0->code()); |
426 } | 426 } |
427 for (int i = 0; i < 3; i++) { | 427 for (int i = 0; i < 3; i++) { |
428 LocalContext env; | 428 LocalContext env; |
429 env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"), | 429 env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"), |
430 v8::Integer::New(CcTest::isolate(), i)); | 430 v8::Integer::New(CcTest::isolate(), i)); |
431 script->GetUnboundScript()->BindToCurrentContext()->Run(); | 431 script->GetUnboundScript()->BindToCurrentContext()->Run(); |
432 CompileRun( | 432 CompileRun( |
433 "var closure0 = MakeClosure();" | 433 "var closure0 = MakeClosure();" |
434 "%DebugPrint(closure0());" | 434 "%DebugPrint(closure0());" |
435 "%OptimizeFunctionOnNextCall(closure0);" | 435 "%OptimizeFunctionOnNextCall(closure0);" |
436 "%DebugPrint(closure0());" | 436 "%DebugPrint(closure0());" |
437 "var closure1 = MakeClosure();" | 437 "var closure1 = MakeClosure();" |
438 "var closure2 = MakeClosure();"); | 438 "var closure2 = MakeClosure();"); |
439 Handle<JSFunction> fun1 = v8::Utils::OpenHandle( | 439 Handle<JSFunction> fun1 = Handle<JSFunction>::cast( |
440 *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure1")))); | 440 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
441 Handle<JSFunction> fun2 = v8::Utils::OpenHandle( | 441 env->Global()->Get(v8_str("closure1"))))); |
442 *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure2")))); | 442 Handle<JSFunction> fun2 = Handle<JSFunction>::cast( |
| 443 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 444 env->Global()->Get(v8_str("closure2"))))); |
443 CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); | 445 CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
444 CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); | 446 CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
445 CHECK_EQ(*reference_code, fun1->code()); | 447 CHECK_EQ(*reference_code, fun1->code()); |
446 CHECK_EQ(*reference_code, fun2->code()); | 448 CHECK_EQ(*reference_code, fun2->code()); |
447 } | 449 } |
448 } | 450 } |
449 | 451 |
450 | 452 |
451 // Test that optimized code for different closures is actually shared | 453 // Test that optimized code for different closures is actually shared |
452 // immediately by the FastNewClosureStub without context-dependent entries. | 454 // immediately by the FastNewClosureStub without context-dependent entries. |
(...skipping 14 matching lines...) Expand all Loading... |
467 { | 469 { |
468 LocalContext env; | 470 LocalContext env; |
469 env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"), | 471 env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"), |
470 v8::Integer::New(CcTest::isolate(), 23)); | 472 v8::Integer::New(CcTest::isolate(), 23)); |
471 script->GetUnboundScript()->BindToCurrentContext()->Run(); | 473 script->GetUnboundScript()->BindToCurrentContext()->Run(); |
472 CompileRun( | 474 CompileRun( |
473 "var closure0 = MakeClosure();" | 475 "var closure0 = MakeClosure();" |
474 "%DebugPrint(closure0());" | 476 "%DebugPrint(closure0());" |
475 "%OptimizeFunctionOnNextCall(closure0);" | 477 "%OptimizeFunctionOnNextCall(closure0);" |
476 "%DebugPrint(closure0());"); | 478 "%DebugPrint(closure0());"); |
477 Handle<JSFunction> fun0 = v8::Utils::OpenHandle( | 479 Handle<JSFunction> fun0 = Handle<JSFunction>::cast( |
478 *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure0")))); | 480 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 481 env->Global()->Get(v8_str("closure0"))))); |
479 CHECK(fun0->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); | 482 CHECK(fun0->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
480 reference_code = handle(fun0->code()); | 483 reference_code = handle(fun0->code()); |
481 // Evict only the context-dependent entry from the optimized code map. This | 484 // Evict only the context-dependent entry from the optimized code map. This |
482 // leaves it in a state where only the context-independent entry exists. | 485 // leaves it in a state where only the context-independent entry exists. |
483 fun0->shared()->TrimOptimizedCodeMap(SharedFunctionInfo::kEntryLength); | 486 fun0->shared()->TrimOptimizedCodeMap(SharedFunctionInfo::kEntryLength); |
484 } | 487 } |
485 for (int i = 0; i < 3; i++) { | 488 for (int i = 0; i < 3; i++) { |
486 LocalContext env; | 489 LocalContext env; |
487 env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"), | 490 env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"), |
488 v8::Integer::New(CcTest::isolate(), i)); | 491 v8::Integer::New(CcTest::isolate(), i)); |
489 script->GetUnboundScript()->BindToCurrentContext()->Run(); | 492 script->GetUnboundScript()->BindToCurrentContext()->Run(); |
490 CompileRun( | 493 CompileRun( |
491 "var closure0 = MakeClosure();" | 494 "var closure0 = MakeClosure();" |
492 "%DebugPrint(closure0());" | 495 "%DebugPrint(closure0());" |
493 "%OptimizeFunctionOnNextCall(closure0);" | 496 "%OptimizeFunctionOnNextCall(closure0);" |
494 "%DebugPrint(closure0());" | 497 "%DebugPrint(closure0());" |
495 "var closure1 = MakeClosure();" | 498 "var closure1 = MakeClosure();" |
496 "var closure2 = MakeClosure();"); | 499 "var closure2 = MakeClosure();"); |
497 Handle<JSFunction> fun1 = v8::Utils::OpenHandle( | 500 Handle<JSFunction> fun1 = Handle<JSFunction>::cast( |
498 *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure1")))); | 501 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
499 Handle<JSFunction> fun2 = v8::Utils::OpenHandle( | 502 env->Global()->Get(v8_str("closure1"))))); |
500 *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure2")))); | 503 Handle<JSFunction> fun2 = Handle<JSFunction>::cast( |
| 504 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 505 env->Global()->Get(v8_str("closure2"))))); |
501 CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); | 506 CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
502 CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); | 507 CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
503 CHECK_EQ(*reference_code, fun1->code()); | 508 CHECK_EQ(*reference_code, fun1->code()); |
504 CHECK_EQ(*reference_code, fun2->code()); | 509 CHECK_EQ(*reference_code, fun2->code()); |
505 } | 510 } |
506 } | 511 } |
507 | 512 |
508 | 513 |
509 TEST(CompileFunctionInContext) { | 514 TEST(CompileFunctionInContext) { |
510 CcTest::InitializeVM(); | 515 CcTest::InitializeVM(); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 CHECK(!stack.IsEmpty()); | 642 CHECK(!stack.IsEmpty()); |
638 CHECK(stack->GetFrameCount() > 0); | 643 CHECK(stack->GetFrameCount() > 0); |
639 v8::Local<v8::StackFrame> frame = stack->GetFrame(0); | 644 v8::Local<v8::StackFrame> frame = stack->GetFrame(0); |
640 CHECK_EQ(23, frame->GetLineNumber()); | 645 CHECK_EQ(23, frame->GetLineNumber()); |
641 CHECK_EQ(42 + strlen("throw "), static_cast<unsigned>(frame->GetColumn())); | 646 CHECK_EQ(42 + strlen("throw "), static_cast<unsigned>(frame->GetColumn())); |
642 } | 647 } |
643 | 648 |
644 | 649 |
645 #ifdef ENABLE_DISASSEMBLER | 650 #ifdef ENABLE_DISASSEMBLER |
646 static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj, | 651 static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj, |
647 const char* property_name) { | 652 const char* property_name) { |
648 v8::Local<v8::Function> fun = | 653 v8::Local<v8::Function> fun = |
649 v8::Local<v8::Function>::Cast(obj->Get(v8_str(property_name))); | 654 v8::Local<v8::Function>::Cast(obj->Get(v8_str(property_name))); |
650 return v8::Utils::OpenHandle(*fun); | 655 return Handle<JSFunction>::cast(v8::Utils::OpenHandle(*fun)); |
651 } | 656 } |
652 | 657 |
653 | 658 |
654 static void CheckCodeForUnsafeLiteral(Handle<JSFunction> f) { | 659 static void CheckCodeForUnsafeLiteral(Handle<JSFunction> f) { |
655 // Create a disassembler with default name lookup. | 660 // Create a disassembler with default name lookup. |
656 disasm::NameConverter name_converter; | 661 disasm::NameConverter name_converter; |
657 disasm::Disassembler d(name_converter); | 662 disasm::Disassembler d(name_converter); |
658 | 663 |
659 if (f->code()->kind() == Code::FUNCTION) { | 664 if (f->code()->kind() == Code::FUNCTION) { |
660 Address pc = f->code()->instruction_start(); | 665 Address pc = f->code()->instruction_start(); |
(...skipping 29 matching lines...) Expand all Loading... |
690 CompileRun("function f() { a = 12345678 }; f();"); | 695 CompileRun("function f() { a = 12345678 }; f();"); |
691 CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f")); | 696 CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f")); |
692 CompileRun("function f(x) { a = 12345678 + x}; f(1);"); | 697 CompileRun("function f(x) { a = 12345678 + x}; f(1);"); |
693 CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f")); | 698 CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f")); |
694 CompileRun("function f(x) { var arguments = 1; x += 12345678}; f(1);"); | 699 CompileRun("function f(x) { var arguments = 1; x += 12345678}; f(1);"); |
695 CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f")); | 700 CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f")); |
696 CompileRun("function f(x) { var arguments = 1; x = 12345678}; f(1);"); | 701 CompileRun("function f(x) { var arguments = 1; x = 12345678}; f(1);"); |
697 CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f")); | 702 CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f")); |
698 } | 703 } |
699 #endif | 704 #endif |
OLD | NEW |