Chromium Code Reviews| 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 |