OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
512 ToBoolean(true_target, false_target); | 512 ToBoolean(true_target, false_target); |
513 } | 513 } |
514 ASSERT(!force_cc || !has_valid_frame() || has_cc()); | 514 ASSERT(!force_cc || !has_valid_frame() || has_cc()); |
515 ASSERT(!has_valid_frame() || | 515 ASSERT(!has_valid_frame() || |
516 (has_cc() && frame_->height() == original_height) || | 516 (has_cc() && frame_->height() == original_height) || |
517 (!has_cc() && frame_->height() == original_height + 1)); | 517 (!has_cc() && frame_->height() == original_height + 1)); |
518 } | 518 } |
519 | 519 |
520 | 520 |
521 void CodeGenerator::Load(Expression* expr) { | 521 void CodeGenerator::Load(Expression* expr) { |
522 frame_->AssertIsNotSpilled(); | |
522 #ifdef DEBUG | 523 #ifdef DEBUG |
523 int original_height = frame_->height(); | 524 int original_height = frame_->height(); |
524 #endif | 525 #endif |
525 JumpTarget true_target; | 526 JumpTarget true_target; |
526 JumpTarget false_target; | 527 JumpTarget false_target; |
527 LoadCondition(expr, &true_target, &false_target, false); | 528 LoadCondition(expr, &true_target, &false_target, false); |
528 | 529 |
529 if (has_cc()) { | 530 if (has_cc()) { |
530 // Convert cc_reg_ into a boolean value. | 531 // Convert cc_reg_ into a boolean value. |
531 JumpTarget loaded; | 532 JumpTarget loaded; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
668 } | 669 } |
669 | 670 |
670 | 671 |
671 Reference::Reference(CodeGenerator* cgen, | 672 Reference::Reference(CodeGenerator* cgen, |
672 Expression* expression, | 673 Expression* expression, |
673 bool persist_after_get) | 674 bool persist_after_get) |
674 : cgen_(cgen), | 675 : cgen_(cgen), |
675 expression_(expression), | 676 expression_(expression), |
676 type_(ILLEGAL), | 677 type_(ILLEGAL), |
677 persist_after_get_(persist_after_get) { | 678 persist_after_get_(persist_after_get) { |
679 cgen->frame()->AssertIsNotSpilled(); | |
678 cgen->LoadReference(this); | 680 cgen->LoadReference(this); |
679 } | 681 } |
680 | 682 |
681 | 683 |
682 Reference::~Reference() { | 684 Reference::~Reference() { |
683 ASSERT(is_unloaded() || is_illegal()); | 685 ASSERT(is_unloaded() || is_illegal()); |
684 } | 686 } |
685 | 687 |
686 | 688 |
687 void CodeGenerator::LoadReference(Reference* ref) { | 689 void CodeGenerator::LoadReference(Reference* ref) { |
(...skipping 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1878 | 1880 |
1879 | 1881 |
1880 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { | 1882 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { |
1881 Comment cmnt(masm_, "[ BreakStatement"); | 1883 Comment cmnt(masm_, "[ BreakStatement"); |
1882 CodeForStatementPosition(node); | 1884 CodeForStatementPosition(node); |
1883 node->target()->break_target()->Jump(); | 1885 node->target()->break_target()->Jump(); |
1884 } | 1886 } |
1885 | 1887 |
1886 | 1888 |
1887 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 1889 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { |
1888 frame_->SpillAll(); | |
1889 Comment cmnt(masm_, "[ ReturnStatement"); | 1890 Comment cmnt(masm_, "[ ReturnStatement"); |
1890 | 1891 |
1891 CodeForStatementPosition(node); | 1892 CodeForStatementPosition(node); |
1892 Load(node->expression()); | 1893 Load(node->expression()); |
1894 frame_->PopToR0(); | |
1895 frame_->PrepareForReturn(); | |
1893 if (function_return_is_shadowed_) { | 1896 if (function_return_is_shadowed_) { |
1894 frame_->EmitPop(r0); | |
1895 function_return_.Jump(); | 1897 function_return_.Jump(); |
1896 } else { | 1898 } else { |
1897 // Pop the result from the frame and prepare the frame for | 1899 // Pop the result from the frame and prepare the frame for |
1898 // returning thus making it easier to merge. | 1900 // returning thus making it easier to merge. |
1899 frame_->PopToR0(); | |
1900 frame_->PrepareForReturn(); | |
1901 if (function_return_.is_bound()) { | 1901 if (function_return_.is_bound()) { |
1902 // If the function return label is already bound we reuse the | 1902 // If the function return label is already bound we reuse the |
1903 // code by jumping to the return site. | 1903 // code by jumping to the return site. |
1904 function_return_.Jump(); | 1904 function_return_.Jump(); |
1905 } else { | 1905 } else { |
1906 function_return_.Bind(); | 1906 function_return_.Bind(); |
1907 GenerateReturnSequence(); | 1907 GenerateReturnSequence(); |
1908 } | 1908 } |
1909 } | 1909 } |
1910 } | 1910 } |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2286 } | 2286 } |
2287 DecrementLoopNesting(); | 2287 DecrementLoopNesting(); |
2288 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 2288 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
2289 } | 2289 } |
2290 | 2290 |
2291 | 2291 |
2292 void CodeGenerator::VisitForInStatement(ForInStatement* node) { | 2292 void CodeGenerator::VisitForInStatement(ForInStatement* node) { |
2293 #ifdef DEBUG | 2293 #ifdef DEBUG |
2294 int original_height = frame_->height(); | 2294 int original_height = frame_->height(); |
2295 #endif | 2295 #endif |
2296 VirtualFrame::SpilledScope spilled_scope(frame_); | |
2297 Comment cmnt(masm_, "[ ForInStatement"); | 2296 Comment cmnt(masm_, "[ ForInStatement"); |
2298 CodeForStatementPosition(node); | 2297 CodeForStatementPosition(node); |
2299 | 2298 |
2300 JumpTarget primitive; | 2299 JumpTarget primitive; |
2301 JumpTarget jsobject; | 2300 JumpTarget jsobject; |
2302 JumpTarget fixed_array; | 2301 JumpTarget fixed_array; |
2303 JumpTarget entry(JumpTarget::BIDIRECTIONAL); | 2302 JumpTarget entry(JumpTarget::BIDIRECTIONAL); |
2304 JumpTarget end_del_check; | 2303 JumpTarget end_del_check; |
2305 JumpTarget exit; | 2304 JumpTarget exit; |
2306 | 2305 |
2307 // Get the object to enumerate over (converted to JSObject). | 2306 // Get the object to enumerate over (converted to JSObject). |
2308 Load(node->enumerable()); | 2307 Load(node->enumerable()); |
2309 | 2308 |
2309 VirtualFrame::SpilledScope spilled_scope(frame_); | |
2310 // Both SpiderMonkey and kjs ignore null and undefined in contrast | 2310 // Both SpiderMonkey and kjs ignore null and undefined in contrast |
2311 // to the specification. 12.6.4 mandates a call to ToObject. | 2311 // to the specification. 12.6.4 mandates a call to ToObject. |
2312 frame_->EmitPop(r0); | 2312 frame_->EmitPop(r0); |
2313 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 2313 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
2314 __ cmp(r0, ip); | 2314 __ cmp(r0, ip); |
2315 exit.Branch(eq); | 2315 exit.Branch(eq); |
2316 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 2316 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
2317 __ cmp(r0, ip); | 2317 __ cmp(r0, ip); |
2318 exit.Branch(eq); | 2318 exit.Branch(eq); |
2319 | 2319 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2469 frame_->EmitPush(r3); // push entry | 2469 frame_->EmitPush(r3); // push entry |
2470 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS, 2); | 2470 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS, 2); |
2471 __ mov(r3, Operand(r0), SetCC); | 2471 __ mov(r3, Operand(r0), SetCC); |
2472 // If the property has been removed while iterating, we just skip it. | 2472 // If the property has been removed while iterating, we just skip it. |
2473 node->continue_target()->Branch(eq); | 2473 node->continue_target()->Branch(eq); |
2474 | 2474 |
2475 end_del_check.Bind(); | 2475 end_del_check.Bind(); |
2476 // Store the entry in the 'each' expression and take another spin in the | 2476 // Store the entry in the 'each' expression and take another spin in the |
2477 // loop. r3: i'th entry of the enum cache (or string there of) | 2477 // loop. r3: i'th entry of the enum cache (or string there of) |
2478 frame_->EmitPush(r3); // push entry | 2478 frame_->EmitPush(r3); // push entry |
2479 { Reference each(this, node->each()); | 2479 { VirtualFrame::RegisterAllocationScope scope(this); |
2480 Reference each(this, node->each()); | |
2480 if (!each.is_illegal()) { | 2481 if (!each.is_illegal()) { |
2481 if (each.size() > 0) { | 2482 if (each.size() > 0) { |
2483 // Loading a reference may leave the frame in an unspilled state. | |
2484 frame_->SpillAll(); // Sync stack to memory. | |
2485 // Get the value (under the reference on the stack) from memory. | |
2482 __ ldr(r0, frame_->ElementAt(each.size())); | 2486 __ ldr(r0, frame_->ElementAt(each.size())); |
2483 frame_->EmitPush(r0); | 2487 frame_->EmitPush(r0); |
2484 each.SetValue(NOT_CONST_INIT, UNLIKELY_SMI); | 2488 each.SetValue(NOT_CONST_INIT, UNLIKELY_SMI); |
2485 frame_->Drop(2); | 2489 frame_->Drop(2); // The result of the set and the extra pushed value. |
2486 } else { | 2490 } else { |
2487 // If the reference was to a slot we rely on the convenient property | 2491 // If the reference was to a slot we rely on the convenient property |
2488 // that it doesn't matter whether a value (eg, r3 pushed above) is | 2492 // that it doesn't matter whether a value (eg, ebx pushed above) is |
2489 // right on top of or right underneath a zero-sized reference. | 2493 // right on top of or right underneath a zero-sized reference. |
2490 each.SetValue(NOT_CONST_INIT, UNLIKELY_SMI); | 2494 each.SetValue(NOT_CONST_INIT, UNLIKELY_SMI); |
2491 frame_->Drop(); | 2495 frame_->Drop(1); // Drop the result of the set operation. |
2492 } | 2496 } |
2493 } | 2497 } |
2494 } | 2498 } |
2495 // Body. | 2499 // Body. |
2496 CheckStack(); // TODO(1222600): ignore if body contains calls. | 2500 CheckStack(); // TODO(1222600): ignore if body contains calls. |
2497 Visit(node->body()); | 2501 { VirtualFrame::RegisterAllocationScope scope(this); |
2502 Visit(node->body()); | |
2503 } | |
2498 | 2504 |
2499 // Next. Reestablish a spilled frame in case we are coming here via | 2505 // Next. Reestablish a spilled frame in case we are coming here via |
2500 // a continue in the body. | 2506 // a continue in the body. |
2501 node->continue_target()->Bind(); | 2507 node->continue_target()->Bind(); |
2502 frame_->SpillAll(); | 2508 frame_->SpillAll(); |
2503 frame_->EmitPop(r0); | 2509 frame_->EmitPop(r0); |
2504 __ add(r0, r0, Operand(Smi::FromInt(1))); | 2510 __ add(r0, r0, Operand(Smi::FromInt(1))); |
2505 frame_->EmitPush(r0); | 2511 frame_->EmitPush(r0); |
2506 entry.Jump(); | 2512 entry.Jump(); |
2507 | 2513 |
(...skipping 26 matching lines...) Expand all Loading... | |
2534 frame_->EmitPush(r0); | 2540 frame_->EmitPush(r0); |
2535 | 2541 |
2536 // Store the caught exception in the catch variable. | 2542 // Store the caught exception in the catch variable. |
2537 Variable* catch_var = node->catch_var()->var(); | 2543 Variable* catch_var = node->catch_var()->var(); |
2538 ASSERT(catch_var != NULL && catch_var->slot() != NULL); | 2544 ASSERT(catch_var != NULL && catch_var->slot() != NULL); |
2539 StoreToSlot(catch_var->slot(), NOT_CONST_INIT); | 2545 StoreToSlot(catch_var->slot(), NOT_CONST_INIT); |
2540 | 2546 |
2541 // Remove the exception from the stack. | 2547 // Remove the exception from the stack. |
2542 frame_->Drop(); | 2548 frame_->Drop(); |
2543 | 2549 |
2544 VisitStatements(node->catch_block()->statements()); | 2550 { VirtualFrame::RegisterAllocationScope scope(this); |
2551 VisitStatements(node->catch_block()->statements()); | |
2552 } | |
2545 if (frame_ != NULL) { | 2553 if (frame_ != NULL) { |
2546 exit.Jump(); | 2554 exit.Jump(); |
2547 } | 2555 } |
2548 | 2556 |
2549 | 2557 |
2550 // --- Try block --- | 2558 // --- Try block --- |
2551 try_block.Bind(); | 2559 try_block.Bind(); |
2552 | 2560 |
2553 frame_->PushTryHandler(TRY_CATCH_HANDLER); | 2561 frame_->PushTryHandler(TRY_CATCH_HANDLER); |
2554 int handler_height = frame_->height(); | 2562 int handler_height = frame_->height(); |
(...skipping 14 matching lines...) Expand all Loading... | |
2569 bool function_return_was_shadowed = function_return_is_shadowed_; | 2577 bool function_return_was_shadowed = function_return_is_shadowed_; |
2570 function_return_is_shadowed_ = true; | 2578 function_return_is_shadowed_ = true; |
2571 ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_); | 2579 ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_); |
2572 | 2580 |
2573 // Add the remaining shadow targets. | 2581 // Add the remaining shadow targets. |
2574 for (int i = 0; i < nof_escapes; i++) { | 2582 for (int i = 0; i < nof_escapes; i++) { |
2575 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2583 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
2576 } | 2584 } |
2577 | 2585 |
2578 // Generate code for the statements in the try block. | 2586 // Generate code for the statements in the try block. |
2579 VisitStatements(node->try_block()->statements()); | 2587 { VirtualFrame::RegisterAllocationScope scope(this); |
2588 VisitStatements(node->try_block()->statements()); | |
2589 } | |
2580 | 2590 |
2581 // Stop the introduced shadowing and count the number of required unlinks. | 2591 // Stop the introduced shadowing and count the number of required unlinks. |
2582 // After shadowing stops, the original labels are unshadowed and the | 2592 // After shadowing stops, the original labels are unshadowed and the |
2583 // LabelShadows represent the formerly shadowing labels. | 2593 // LabelShadows represent the formerly shadowing labels. |
2584 bool has_unlinks = false; | 2594 bool has_unlinks = false; |
2585 for (int i = 0; i < shadows.length(); i++) { | 2595 for (int i = 0; i < shadows.length(); i++) { |
2586 shadows[i]->StopShadowing(); | 2596 shadows[i]->StopShadowing(); |
2587 has_unlinks = has_unlinks || shadows[i]->is_linked(); | 2597 has_unlinks = has_unlinks || shadows[i]->is_linked(); |
2588 } | 2598 } |
2589 function_return_is_shadowed_ = function_return_was_shadowed; | 2599 function_return_is_shadowed_ = function_return_was_shadowed; |
2590 | 2600 |
2591 // Get an external reference to the handler address. | 2601 // Get an external reference to the handler address. |
2592 ExternalReference handler_address(Top::k_handler_address); | 2602 ExternalReference handler_address(Top::k_handler_address); |
2593 | 2603 |
2594 // If we can fall off the end of the try block, unlink from try chain. | 2604 // If we can fall off the end of the try block, unlink from try chain. |
2595 if (has_valid_frame()) { | 2605 if (has_valid_frame()) { |
2596 // The next handler address is on top of the frame. Unlink from | 2606 // The next handler address is on top of the frame. Unlink from |
2597 // the handler list and drop the rest of this handler from the | 2607 // the handler list and drop the rest of this handler from the |
2598 // frame. | 2608 // frame. |
2599 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 2609 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
Søren Thygesen Gjesse
2010/08/16 07:15:36
Maybe add the r0 comment here as well.
| |
2600 frame_->EmitPop(r1); | 2610 frame_->EmitPop(r1); |
2601 __ mov(r3, Operand(handler_address)); | 2611 __ mov(r3, Operand(handler_address)); |
2602 __ str(r1, MemOperand(r3)); | 2612 __ str(r1, MemOperand(r3)); |
2603 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 2613 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
2604 if (has_unlinks) { | 2614 if (has_unlinks) { |
2605 exit.Jump(); | 2615 exit.Jump(); |
2606 } | 2616 } |
2607 } | 2617 } |
2608 | 2618 |
2609 // Generate unlink code for the (formerly) shadowing labels that have been | 2619 // Generate unlink code for the (formerly) shadowing labels that have been |
2610 // jumped to. Deallocate each shadow target. | 2620 // jumped to. Deallocate each shadow target. |
2611 for (int i = 0; i < shadows.length(); i++) { | 2621 for (int i = 0; i < shadows.length(); i++) { |
2612 if (shadows[i]->is_linked()) { | 2622 if (shadows[i]->is_linked()) { |
2613 // Unlink from try chain; | 2623 // Unlink from try chain; |
2614 shadows[i]->Bind(); | 2624 shadows[i]->Bind(); |
2615 // Because we can be jumping here (to spilled code) from unspilled | 2625 // Because we can be jumping here (to spilled code) from unspilled |
2616 // code, we need to reestablish a spilled frame at this block. | 2626 // code, we need to reestablish a spilled frame at this block. |
2617 frame_->SpillAll(); | 2627 frame_->SpillAll(); |
2618 | 2628 |
2619 // Reload sp from the top handler, because some statements that we | 2629 // Reload sp from the top handler, because some statements that we |
2620 // break from (eg, for...in) may have left stuff on the stack. | 2630 // break from (eg, for...in) may have left stuff on the stack. |
2621 __ mov(r3, Operand(handler_address)); | 2631 __ mov(r3, Operand(handler_address)); |
2622 __ ldr(sp, MemOperand(r3)); | 2632 __ ldr(sp, MemOperand(r3)); |
2623 frame_->Forget(frame_->height() - handler_height); | 2633 frame_->Forget(frame_->height() - handler_height); |
2624 | 2634 |
2625 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 2635 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
2626 frame_->EmitPop(r1); | 2636 frame_->EmitPop(r1); // r0 can contain the return value. |
2627 __ str(r1, MemOperand(r3)); | 2637 __ str(r1, MemOperand(r3)); |
2628 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 2638 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
2629 | 2639 |
2630 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) { | 2640 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) { |
2631 frame_->PrepareForReturn(); | 2641 frame_->PrepareForReturn(); |
2632 } | 2642 } |
2633 shadows[i]->other_target()->Jump(); | 2643 shadows[i]->other_target()->Jump(); |
2634 } | 2644 } |
2635 } | 2645 } |
2636 | 2646 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2683 bool function_return_was_shadowed = function_return_is_shadowed_; | 2693 bool function_return_was_shadowed = function_return_is_shadowed_; |
2684 function_return_is_shadowed_ = true; | 2694 function_return_is_shadowed_ = true; |
2685 ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_); | 2695 ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_); |
2686 | 2696 |
2687 // Add the remaining shadow targets. | 2697 // Add the remaining shadow targets. |
2688 for (int i = 0; i < nof_escapes; i++) { | 2698 for (int i = 0; i < nof_escapes; i++) { |
2689 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2699 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
2690 } | 2700 } |
2691 | 2701 |
2692 // Generate code for the statements in the try block. | 2702 // Generate code for the statements in the try block. |
2693 VisitStatements(node->try_block()->statements()); | 2703 { VirtualFrame::RegisterAllocationScope scope(this); |
2704 VisitStatements(node->try_block()->statements()); | |
2705 } | |
2694 | 2706 |
2695 // Stop the introduced shadowing and count the number of required unlinks. | 2707 // Stop the introduced shadowing and count the number of required unlinks. |
2696 // After shadowing stops, the original labels are unshadowed and the | 2708 // After shadowing stops, the original labels are unshadowed and the |
2697 // LabelShadows represent the formerly shadowing labels. | 2709 // LabelShadows represent the formerly shadowing labels. |
2698 int nof_unlinks = 0; | 2710 int nof_unlinks = 0; |
2699 for (int i = 0; i < shadows.length(); i++) { | 2711 for (int i = 0; i < shadows.length(); i++) { |
2700 shadows[i]->StopShadowing(); | 2712 shadows[i]->StopShadowing(); |
2701 if (shadows[i]->is_linked()) nof_unlinks++; | 2713 if (shadows[i]->is_linked()) nof_unlinks++; |
2702 } | 2714 } |
2703 function_return_is_shadowed_ = function_return_was_shadowed; | 2715 function_return_is_shadowed_ = function_return_was_shadowed; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2773 // --- Finally block --- | 2785 // --- Finally block --- |
2774 finally_block.Bind(); | 2786 finally_block.Bind(); |
2775 | 2787 |
2776 // Push the state on the stack. | 2788 // Push the state on the stack. |
2777 frame_->EmitPush(r2); | 2789 frame_->EmitPush(r2); |
2778 | 2790 |
2779 // We keep two elements on the stack - the (possibly faked) result | 2791 // We keep two elements on the stack - the (possibly faked) result |
2780 // and the state - while evaluating the finally block. | 2792 // and the state - while evaluating the finally block. |
2781 // | 2793 // |
2782 // Generate code for the statements in the finally block. | 2794 // Generate code for the statements in the finally block. |
2783 VisitStatements(node->finally_block()->statements()); | 2795 { VirtualFrame::RegisterAllocationScope scope(this); |
2796 VisitStatements(node->finally_block()->statements()); | |
2797 } | |
2784 | 2798 |
2785 if (has_valid_frame()) { | 2799 if (has_valid_frame()) { |
2786 // Restore state and return value or faked TOS. | 2800 // Restore state and return value or faked TOS. |
2787 frame_->EmitPop(r2); | 2801 frame_->EmitPop(r2); |
2788 frame_->EmitPop(r0); | 2802 frame_->EmitPop(r0); |
2789 } | 2803 } |
2790 | 2804 |
2791 // Generate code to jump to the right destination for all used | 2805 // Generate code to jump to the right destination for all used |
2792 // formerly shadowing targets. Deallocate each shadow target. | 2806 // formerly shadowing targets. Deallocate each shadow target. |
2793 for (int i = 0; i < shadows.length(); i++) { | 2807 for (int i = 0; i < shadows.length(); i++) { |
(...skipping 1159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3953 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 3967 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
3954 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); | 3968 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); |
3955 CodeForSourcePosition(node->position()); | 3969 CodeForSourcePosition(node->position()); |
3956 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, | 3970 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, |
3957 arg_count + 1); | 3971 arg_count + 1); |
3958 __ ldr(cp, frame_->Context()); | 3972 __ ldr(cp, frame_->Context()); |
3959 frame_->EmitPush(r0); | 3973 frame_->EmitPush(r0); |
3960 | 3974 |
3961 } else if (var != NULL && var->slot() != NULL && | 3975 } else if (var != NULL && var->slot() != NULL && |
3962 var->slot()->type() == Slot::LOOKUP) { | 3976 var->slot()->type() == Slot::LOOKUP) { |
3963 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3964 // ---------------------------------- | 3977 // ---------------------------------- |
3965 // JavaScript examples: | 3978 // JavaScript examples: |
3966 // | 3979 // |
3967 // with (obj) foo(1, 2, 3) // foo may be in obj. | 3980 // with (obj) foo(1, 2, 3) // foo may be in obj. |
3968 // | 3981 // |
3969 // function f() {}; | 3982 // function f() {}; |
3970 // function g() { | 3983 // function g() { |
3971 // eval(...); | 3984 // eval(...); |
3972 // f(); // f could be in extension object. | 3985 // f(); // f could be in extension object. |
3973 // } | 3986 // } |
3974 // ---------------------------------- | 3987 // ---------------------------------- |
3975 | 3988 |
3976 // JumpTargets do not yet support merging frames so the frame must be | |
3977 // spilled when jumping to these targets. | |
3978 JumpTarget slow, done; | 3989 JumpTarget slow, done; |
3979 | 3990 |
3980 // Generate fast case for loading functions from slots that | 3991 // Generate fast case for loading functions from slots that |
3981 // correspond to local/global variables or arguments unless they | 3992 // correspond to local/global variables or arguments unless they |
3982 // are shadowed by eval-introduced bindings. | 3993 // are shadowed by eval-introduced bindings. |
3983 EmitDynamicLoadFromSlotFastCase(var->slot(), | 3994 EmitDynamicLoadFromSlotFastCase(var->slot(), |
3984 NOT_INSIDE_TYPEOF, | 3995 NOT_INSIDE_TYPEOF, |
3985 &slow, | 3996 &slow, |
3986 &done); | 3997 &done); |
3987 | 3998 |
3988 slow.Bind(); | 3999 slow.Bind(); |
3989 // Load the function | 4000 // Load the function |
3990 frame_->EmitPush(cp); | 4001 frame_->EmitPush(cp); |
3991 __ mov(r0, Operand(var->name())); | 4002 frame_->EmitPush(Operand(var->name())); |
3992 frame_->EmitPush(r0); | |
3993 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); | 4003 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); |
3994 // r0: slot value; r1: receiver | 4004 // r0: slot value; r1: receiver |
3995 | 4005 |
3996 // Load the receiver. | 4006 // Load the receiver. |
3997 frame_->EmitPush(r0); // function | 4007 frame_->EmitPush(r0); // function |
3998 frame_->EmitPush(r1); // receiver | 4008 frame_->EmitPush(r1); // receiver |
3999 | 4009 |
4000 // If fast case code has been generated, emit code to push the | 4010 // If fast case code has been generated, emit code to push the |
4001 // function and receiver and have the slow path jump around this | 4011 // function and receiver and have the slow path jump around this |
4002 // code. | 4012 // code. |
4003 if (done.is_linked()) { | 4013 if (done.is_linked()) { |
4004 JumpTarget call; | 4014 JumpTarget call; |
4005 call.Jump(); | 4015 call.Jump(); |
4006 done.Bind(); | 4016 done.Bind(); |
4007 frame_->EmitPush(r0); // function | 4017 frame_->EmitPush(r0); // function |
4008 LoadGlobalReceiver(r1); // receiver | 4018 LoadGlobalReceiver(VirtualFrame::scratch0()); // receiver |
4009 call.Bind(); | 4019 call.Bind(); |
4010 } | 4020 } |
4011 | 4021 |
4012 // Call the function. At this point, everything is spilled but the | 4022 // Call the function. At this point, everything is spilled but the |
4013 // function and receiver are in r0 and r1. | 4023 // function and receiver are in r0 and r1. |
4014 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); | 4024 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
4015 frame_->EmitPush(r0); | 4025 frame_->EmitPush(r0); |
4016 | 4026 |
4017 } else if (property != NULL) { | 4027 } else if (property != NULL) { |
4018 // Check if the key is a literal string. | 4028 // Check if the key is a literal string. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4053 CodeForSourcePosition(node->position()); | 4063 CodeForSourcePosition(node->position()); |
4054 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 4064 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); |
4055 __ ldr(cp, frame_->Context()); | 4065 __ ldr(cp, frame_->Context()); |
4056 frame_->EmitPush(r0); | 4066 frame_->EmitPush(r0); |
4057 } | 4067 } |
4058 | 4068 |
4059 } else { | 4069 } else { |
4060 // ------------------------------------------- | 4070 // ------------------------------------------- |
4061 // JavaScript example: 'array[index](1, 2, 3)' | 4071 // JavaScript example: 'array[index](1, 2, 3)' |
4062 // ------------------------------------------- | 4072 // ------------------------------------------- |
4063 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4064 | |
4065 Load(property->obj()); | 4073 Load(property->obj()); |
4066 if (property->is_synthetic()) { | 4074 if (property->is_synthetic()) { |
4067 Load(property->key()); | 4075 Load(property->key()); |
4068 EmitKeyedLoad(); | 4076 EmitKeyedLoad(); |
4069 // Put the function below the receiver. | 4077 // Put the function below the receiver. |
4070 // Use the global receiver. | 4078 // Use the global receiver. |
4071 frame_->EmitPush(r0); // Function. | 4079 frame_->EmitPush(r0); // Function. |
4072 LoadGlobalReceiver(r0); | 4080 LoadGlobalReceiver(VirtualFrame::scratch0()); |
4073 // Call the function. | 4081 // Call the function. |
4074 CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); | 4082 CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); |
4075 frame_->EmitPush(r0); | 4083 frame_->EmitPush(r0); |
4076 } else { | 4084 } else { |
4077 // Load the arguments. | 4085 // Load the arguments. |
4078 int arg_count = args->length(); | 4086 int arg_count = args->length(); |
4079 for (int i = 0; i < arg_count; i++) { | 4087 for (int i = 0; i < arg_count; i++) { |
4080 Load(args->at(i)); | 4088 Load(args->at(i)); |
4081 } | 4089 } |
4082 | 4090 |
4083 // Set the name register and call the IC initialization code. | 4091 // Set the name register and call the IC initialization code. |
4084 Load(property->key()); | 4092 Load(property->key()); |
4093 frame_->SpillAll(); | |
4085 frame_->EmitPop(r2); // Function name. | 4094 frame_->EmitPop(r2); // Function name. |
4086 | 4095 |
4087 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 4096 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
4088 Handle<Code> stub = ComputeKeyedCallInitialize(arg_count, in_loop); | 4097 Handle<Code> stub = ComputeKeyedCallInitialize(arg_count, in_loop); |
4089 CodeForSourcePosition(node->position()); | 4098 CodeForSourcePosition(node->position()); |
4090 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 4099 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); |
4091 __ ldr(cp, frame_->Context()); | 4100 __ ldr(cp, frame_->Context()); |
4092 frame_->EmitPush(r0); | 4101 frame_->EmitPush(r0); |
4093 } | 4102 } |
4094 } | 4103 } |
4095 | 4104 |
4096 } else { | 4105 } else { |
4097 // ---------------------------------- | 4106 // ---------------------------------- |
4098 // JavaScript example: 'foo(1, 2, 3)' // foo is not global | 4107 // JavaScript example: 'foo(1, 2, 3)' // foo is not global |
4099 // ---------------------------------- | 4108 // ---------------------------------- |
4100 | 4109 |
4101 // Load the function. | 4110 // Load the function. |
4102 Load(function); | 4111 Load(function); |
4103 | 4112 |
4104 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4105 | |
4106 // Pass the global proxy as the receiver. | 4113 // Pass the global proxy as the receiver. |
4107 LoadGlobalReceiver(r0); | 4114 LoadGlobalReceiver(VirtualFrame::scratch0()); |
4108 | 4115 |
4109 // Call the function. | 4116 // Call the function. |
4110 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); | 4117 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
4111 frame_->EmitPush(r0); | 4118 frame_->EmitPush(r0); |
4112 } | 4119 } |
4113 ASSERT_EQ(original_height + 1, frame_->height()); | 4120 ASSERT_EQ(original_height + 1, frame_->height()); |
4114 } | 4121 } |
4115 | 4122 |
4116 | 4123 |
4117 void CodeGenerator::VisitCallNew(CallNew* node) { | 4124 void CodeGenerator::VisitCallNew(CallNew* node) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4152 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); | 4159 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); |
4153 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1); | 4160 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1); |
4154 | 4161 |
4155 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). | 4162 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). |
4156 __ str(r0, frame_->Top()); | 4163 __ str(r0, frame_->Top()); |
4157 ASSERT_EQ(original_height + 1, frame_->height()); | 4164 ASSERT_EQ(original_height + 1, frame_->height()); |
4158 } | 4165 } |
4159 | 4166 |
4160 | 4167 |
4161 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { | 4168 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
4162 JumpTarget leave, null, function, non_function_constructor; | |
4163 Register scratch = VirtualFrame::scratch0(); | 4169 Register scratch = VirtualFrame::scratch0(); |
4170 JumpTarget null, function, leave, non_function_constructor; | |
4164 | 4171 |
4165 // Load the object into register. | 4172 // Load the object into register. |
4166 ASSERT(args->length() == 1); | 4173 ASSERT(args->length() == 1); |
4167 Load(args->at(0)); | 4174 Load(args->at(0)); |
4168 Register tos = frame_->PopToRegister(); | 4175 Register tos = frame_->PopToRegister(); |
4169 | 4176 |
4170 // If the object is a smi, we return null. | 4177 // If the object is a smi, we return null. |
4171 __ tst(tos, Operand(kSmiTagMask)); | 4178 __ tst(tos, Operand(kSmiTagMask)); |
4172 null.Branch(eq); | 4179 null.Branch(eq); |
4173 | 4180 |
(...skipping 7392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11566 __ bind(&string_add_runtime); | 11573 __ bind(&string_add_runtime); |
11567 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 11574 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
11568 } | 11575 } |
11569 | 11576 |
11570 | 11577 |
11571 #undef __ | 11578 #undef __ |
11572 | 11579 |
11573 } } // namespace v8::internal | 11580 } } // namespace v8::internal |
11574 | 11581 |
11575 #endif // V8_TARGET_ARCH_ARM | 11582 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |