| 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 |