| 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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 // parameter twice (e.g., function (x, y, x)), and that parameter | 239 // parameter twice (e.g., function (x, y, x)), and that parameter |
| 240 // needs to be copied into the context, it must be the last argument | 240 // needs to be copied into the context, it must be the last argument |
| 241 // passed to the parameter that needs to be copied. This is a rare | 241 // passed to the parameter that needs to be copied. This is a rare |
| 242 // case so we don't check for it, instead we rely on the copying | 242 // case so we don't check for it, instead we rely on the copying |
| 243 // order: such a parameter is copied repeatedly into the same | 243 // order: such a parameter is copied repeatedly into the same |
| 244 // context location and thus the last value is what is seen inside | 244 // context location and thus the last value is what is seen inside |
| 245 // the function. | 245 // the function. |
| 246 frame_->AssertIsSpilled(); | 246 frame_->AssertIsSpilled(); |
| 247 for (int i = 0; i < scope()->num_parameters(); i++) { | 247 for (int i = 0; i < scope()->num_parameters(); i++) { |
| 248 Variable* par = scope()->parameter(i); | 248 Variable* par = scope()->parameter(i); |
| 249 Slot* slot = par->slot(); | 249 Slot* slot = par->AsSlot(); |
| 250 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 250 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 251 ASSERT(!scope()->is_global_scope()); // No params in global scope. | 251 ASSERT(!scope()->is_global_scope()); // No params in global scope. |
| 252 __ ldr(r1, frame_->ParameterAt(i)); | 252 __ ldr(r1, frame_->ParameterAt(i)); |
| 253 // Loads r2 with context; used below in RecordWrite. | 253 // Loads r2 with context; used below in RecordWrite. |
| 254 __ str(r1, SlotOperand(slot, r2)); | 254 __ str(r1, SlotOperand(slot, r2)); |
| 255 // Load the offset into r3. | 255 // Load the offset into r3. |
| 256 int slot_offset = | 256 int slot_offset = |
| 257 FixedArray::kHeaderSize + slot->index() * kPointerSize; | 257 FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 258 __ RecordWrite(r2, Operand(slot_offset), r3, r1); | 258 __ RecordWrite(r2, Operand(slot_offset), r3, r1); |
| 259 } | 259 } |
| 260 } | 260 } |
| 261 } | 261 } |
| 262 | 262 |
| 263 // Store the arguments object. This must happen after context | 263 // Store the arguments object. This must happen after context |
| 264 // initialization because the arguments object may be stored in | 264 // initialization because the arguments object may be stored in |
| 265 // the context. | 265 // the context. |
| 266 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { | 266 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { |
| 267 StoreArgumentsObject(true); | 267 StoreArgumentsObject(true); |
| 268 } | 268 } |
| 269 | 269 |
| 270 // Initialize ThisFunction reference if present. | 270 // Initialize ThisFunction reference if present. |
| 271 if (scope()->is_function_scope() && scope()->function() != NULL) { | 271 if (scope()->is_function_scope() && scope()->function() != NULL) { |
| 272 frame_->EmitPushRoot(Heap::kTheHoleValueRootIndex); | 272 frame_->EmitPushRoot(Heap::kTheHoleValueRootIndex); |
| 273 StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT); | 273 StoreToSlot(scope()->function()->AsSlot(), NOT_CONST_INIT); |
| 274 } | 274 } |
| 275 | 275 |
| 276 // Initialize the function return target after the locals are set | 276 // Initialize the function return target after the locals are set |
| 277 // up, because it needs the expected frame height from the frame. | 277 // up, because it needs the expected frame height from the frame. |
| 278 function_return_.SetExpectedHeight(); | 278 function_return_.SetExpectedHeight(); |
| 279 function_return_is_shadowed_ = false; | 279 function_return_is_shadowed_ = false; |
| 280 | 280 |
| 281 // Generate code to 'execute' declarations and initialize functions | 281 // Generate code to 'execute' declarations and initialize functions |
| 282 // (source elements). In case of an illegal redeclaration we need to | 282 // (source elements). In case of an illegal redeclaration we need to |
| 283 // handle that instead of processing the declarations. | 283 // handle that instead of processing the declarations. |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 // frame pointer on the stack. | 601 // frame pointer on the stack. |
| 602 const int kReceiverDisplacement = 2 + scope()->num_parameters(); | 602 const int kReceiverDisplacement = 2 + scope()->num_parameters(); |
| 603 __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize)); | 603 __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize)); |
| 604 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); | 604 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); |
| 605 frame_->Adjust(3); | 605 frame_->Adjust(3); |
| 606 __ Push(r2, r1, r0); | 606 __ Push(r2, r1, r0); |
| 607 frame_->CallStub(&stub, 3); | 607 frame_->CallStub(&stub, 3); |
| 608 frame_->EmitPush(r0); | 608 frame_->EmitPush(r0); |
| 609 } | 609 } |
| 610 | 610 |
| 611 Variable* arguments = scope()->arguments()->var(); | 611 Variable* arguments = scope()->arguments(); |
| 612 Variable* shadow = scope()->arguments_shadow()->var(); | 612 Variable* shadow = scope()->arguments_shadow(); |
| 613 ASSERT(arguments != NULL && arguments->slot() != NULL); | 613 ASSERT(arguments != NULL && arguments->AsSlot() != NULL); |
| 614 ASSERT(shadow != NULL && shadow->slot() != NULL); | 614 ASSERT(shadow != NULL && shadow->AsSlot() != NULL); |
| 615 JumpTarget done; | 615 JumpTarget done; |
| 616 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { | 616 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { |
| 617 // We have to skip storing into the arguments slot if it has | 617 // We have to skip storing into the arguments slot if it has |
| 618 // already been written to. This can happen if the a function | 618 // already been written to. This can happen if the a function |
| 619 // has a local variable named 'arguments'. | 619 // has a local variable named 'arguments'. |
| 620 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); | 620 LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF); |
| 621 Register arguments = frame_->PopToRegister(); | 621 Register arguments = frame_->PopToRegister(); |
| 622 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 622 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 623 __ cmp(arguments, ip); | 623 __ cmp(arguments, ip); |
| 624 done.Branch(ne); | 624 done.Branch(ne); |
| 625 } | 625 } |
| 626 StoreToSlot(arguments->slot(), NOT_CONST_INIT); | 626 StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT); |
| 627 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); | 627 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); |
| 628 StoreToSlot(shadow->slot(), NOT_CONST_INIT); | 628 StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT); |
| 629 } | 629 } |
| 630 | 630 |
| 631 | 631 |
| 632 void CodeGenerator::LoadTypeofExpression(Expression* expr) { | 632 void CodeGenerator::LoadTypeofExpression(Expression* expr) { |
| 633 // Special handling of identifiers as subexpressions of typeof. | 633 // Special handling of identifiers as subexpressions of typeof. |
| 634 Variable* variable = expr->AsVariableProxy()->AsVariable(); | 634 Variable* variable = expr->AsVariableProxy()->AsVariable(); |
| 635 if (variable != NULL && !variable->is_this() && variable->is_global()) { | 635 if (variable != NULL && !variable->is_this() && variable->is_global()) { |
| 636 // For a global variable we build the property reference | 636 // For a global variable we build the property reference |
| 637 // <global>.<variable> and perform a (regular non-contextual) property | 637 // <global>.<variable> and perform a (regular non-contextual) property |
| 638 // load to make sure we do not get reference errors. | 638 // load to make sure we do not get reference errors. |
| 639 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); | 639 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); |
| 640 Literal key(variable->name()); | 640 Literal key(variable->name()); |
| 641 Property property(&global, &key, RelocInfo::kNoPosition); | 641 Property property(&global, &key, RelocInfo::kNoPosition); |
| 642 Reference ref(this, &property); | 642 Reference ref(this, &property); |
| 643 ref.GetValue(); | 643 ref.GetValue(); |
| 644 } else if (variable != NULL && variable->slot() != NULL) { | 644 } else if (variable != NULL && variable->AsSlot() != NULL) { |
| 645 // For a variable that rewrites to a slot, we signal it is the immediate | 645 // For a variable that rewrites to a slot, we signal it is the immediate |
| 646 // subexpression of a typeof. | 646 // subexpression of a typeof. |
| 647 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); | 647 LoadFromSlotCheckForArguments(variable->AsSlot(), INSIDE_TYPEOF); |
| 648 } else { | 648 } else { |
| 649 // Anything else can be handled normally. | 649 // Anything else can be handled normally. |
| 650 Load(expr); | 650 Load(expr); |
| 651 } | 651 } |
| 652 } | 652 } |
| 653 | 653 |
| 654 | 654 |
| 655 Reference::Reference(CodeGenerator* cgen, | 655 Reference::Reference(CodeGenerator* cgen, |
| 656 Expression* expression, | 656 Expression* expression, |
| 657 bool persist_after_get) | 657 bool persist_after_get) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 688 Load(property->key()); | 688 Load(property->key()); |
| 689 ref->set_type(Reference::KEYED); | 689 ref->set_type(Reference::KEYED); |
| 690 } | 690 } |
| 691 } else if (var != NULL) { | 691 } else if (var != NULL) { |
| 692 // The expression is a variable proxy that does not rewrite to a | 692 // The expression is a variable proxy that does not rewrite to a |
| 693 // property. Global variables are treated as named property references. | 693 // property. Global variables are treated as named property references. |
| 694 if (var->is_global()) { | 694 if (var->is_global()) { |
| 695 LoadGlobal(); | 695 LoadGlobal(); |
| 696 ref->set_type(Reference::NAMED); | 696 ref->set_type(Reference::NAMED); |
| 697 } else { | 697 } else { |
| 698 ASSERT(var->slot() != NULL); | 698 ASSERT(var->AsSlot() != NULL); |
| 699 ref->set_type(Reference::SLOT); | 699 ref->set_type(Reference::SLOT); |
| 700 } | 700 } |
| 701 } else { | 701 } else { |
| 702 // Anything else is a runtime error. | 702 // Anything else is a runtime error. |
| 703 Load(e); | 703 Load(e); |
| 704 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); | 704 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); |
| 705 } | 705 } |
| 706 } | 706 } |
| 707 | 707 |
| 708 | 708 |
| (...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1711 // give us a megamorphic load site. Not super, but it works. | 1711 // give us a megamorphic load site. Not super, but it works. |
| 1712 Load(applicand); | 1712 Load(applicand); |
| 1713 Handle<String> name = Factory::LookupAsciiSymbol("apply"); | 1713 Handle<String> name = Factory::LookupAsciiSymbol("apply"); |
| 1714 frame_->Dup(); | 1714 frame_->Dup(); |
| 1715 frame_->CallLoadIC(name, RelocInfo::CODE_TARGET); | 1715 frame_->CallLoadIC(name, RelocInfo::CODE_TARGET); |
| 1716 frame_->EmitPush(r0); | 1716 frame_->EmitPush(r0); |
| 1717 | 1717 |
| 1718 // Load the receiver and the existing arguments object onto the | 1718 // Load the receiver and the existing arguments object onto the |
| 1719 // expression stack. Avoid allocating the arguments object here. | 1719 // expression stack. Avoid allocating the arguments object here. |
| 1720 Load(receiver); | 1720 Load(receiver); |
| 1721 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); | 1721 LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF); |
| 1722 | 1722 |
| 1723 // At this point the top two stack elements are probably in registers | 1723 // At this point the top two stack elements are probably in registers |
| 1724 // since they were just loaded. Ensure they are in regs and get the | 1724 // since they were just loaded. Ensure they are in regs and get the |
| 1725 // regs. | 1725 // regs. |
| 1726 Register receiver_reg = frame_->Peek2(); | 1726 Register receiver_reg = frame_->Peek2(); |
| 1727 Register arguments_reg = frame_->Peek(); | 1727 Register arguments_reg = frame_->Peek(); |
| 1728 | 1728 |
| 1729 // From now on the frame is spilled. | 1729 // From now on the frame is spilled. |
| 1730 frame_->SpillAll(); | 1730 frame_->SpillAll(); |
| 1731 | 1731 |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1943 } | 1943 } |
| 1944 | 1944 |
| 1945 | 1945 |
| 1946 void CodeGenerator::VisitDeclaration(Declaration* node) { | 1946 void CodeGenerator::VisitDeclaration(Declaration* node) { |
| 1947 #ifdef DEBUG | 1947 #ifdef DEBUG |
| 1948 int original_height = frame_->height(); | 1948 int original_height = frame_->height(); |
| 1949 #endif | 1949 #endif |
| 1950 Comment cmnt(masm_, "[ Declaration"); | 1950 Comment cmnt(masm_, "[ Declaration"); |
| 1951 Variable* var = node->proxy()->var(); | 1951 Variable* var = node->proxy()->var(); |
| 1952 ASSERT(var != NULL); // must have been resolved | 1952 ASSERT(var != NULL); // must have been resolved |
| 1953 Slot* slot = var->slot(); | 1953 Slot* slot = var->AsSlot(); |
| 1954 | 1954 |
| 1955 // If it was not possible to allocate the variable at compile time, | 1955 // If it was not possible to allocate the variable at compile time, |
| 1956 // we need to "declare" it at runtime to make sure it actually | 1956 // we need to "declare" it at runtime to make sure it actually |
| 1957 // exists in the local context. | 1957 // exists in the local context. |
| 1958 if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1958 if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 1959 // Variables with a "LOOKUP" slot were introduced as non-locals | 1959 // Variables with a "LOOKUP" slot were introduced as non-locals |
| 1960 // during variable resolution and must have mode DYNAMIC. | 1960 // during variable resolution and must have mode DYNAMIC. |
| 1961 ASSERT(var->is_dynamic()); | 1961 ASSERT(var->is_dynamic()); |
| 1962 // For now, just do a runtime call. | 1962 // For now, just do a runtime call. |
| 1963 frame_->EmitPush(cp); | 1963 frame_->EmitPush(cp); |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2473 node->break_target()->SetExpectedHeight(); | 2473 node->break_target()->SetExpectedHeight(); |
| 2474 IncrementLoopNesting(); | 2474 IncrementLoopNesting(); |
| 2475 | 2475 |
| 2476 // We know that the loop index is a smi if it is not modified in the | 2476 // We know that the loop index is a smi if it is not modified in the |
| 2477 // loop body and it is checked against a constant limit in the loop | 2477 // loop body and it is checked against a constant limit in the loop |
| 2478 // condition. In this case, we reset the static type information of the | 2478 // condition. In this case, we reset the static type information of the |
| 2479 // loop index to smi before compiling the body, the update expression, and | 2479 // loop index to smi before compiling the body, the update expression, and |
| 2480 // the bottom check of the loop condition. | 2480 // the bottom check of the loop condition. |
| 2481 TypeInfoCodeGenState type_info_scope(this, | 2481 TypeInfoCodeGenState type_info_scope(this, |
| 2482 node->is_fast_smi_loop() ? | 2482 node->is_fast_smi_loop() ? |
| 2483 node->loop_variable()->slot() : | 2483 node->loop_variable()->AsSlot() : |
| 2484 NULL, | 2484 NULL, |
| 2485 TypeInfo::Smi()); | 2485 TypeInfo::Smi()); |
| 2486 | 2486 |
| 2487 // If there is no update statement, label the top of the loop with the | 2487 // If there is no update statement, label the top of the loop with the |
| 2488 // continue target, otherwise with the loop target. | 2488 // continue target, otherwise with the loop target. |
| 2489 JumpTarget loop(JumpTarget::BIDIRECTIONAL); | 2489 JumpTarget loop(JumpTarget::BIDIRECTIONAL); |
| 2490 if (node->next() == NULL) { | 2490 if (node->next() == NULL) { |
| 2491 node->continue_target()->SetExpectedHeight(); | 2491 node->continue_target()->SetExpectedHeight(); |
| 2492 node->continue_target()->Bind(); | 2492 node->continue_target()->Bind(); |
| 2493 } else { | 2493 } else { |
| 2494 node->continue_target()->SetExpectedHeight(); | 2494 node->continue_target()->SetExpectedHeight(); |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2787 | 2787 |
| 2788 JumpTarget try_block; | 2788 JumpTarget try_block; |
| 2789 JumpTarget exit; | 2789 JumpTarget exit; |
| 2790 | 2790 |
| 2791 try_block.Call(); | 2791 try_block.Call(); |
| 2792 // --- Catch block --- | 2792 // --- Catch block --- |
| 2793 frame_->EmitPush(r0); | 2793 frame_->EmitPush(r0); |
| 2794 | 2794 |
| 2795 // Store the caught exception in the catch variable. | 2795 // Store the caught exception in the catch variable. |
| 2796 Variable* catch_var = node->catch_var()->var(); | 2796 Variable* catch_var = node->catch_var()->var(); |
| 2797 ASSERT(catch_var != NULL && catch_var->slot() != NULL); | 2797 ASSERT(catch_var != NULL && catch_var->AsSlot() != NULL); |
| 2798 StoreToSlot(catch_var->slot(), NOT_CONST_INIT); | 2798 StoreToSlot(catch_var->AsSlot(), NOT_CONST_INIT); |
| 2799 | 2799 |
| 2800 // Remove the exception from the stack. | 2800 // Remove the exception from the stack. |
| 2801 frame_->Drop(); | 2801 frame_->Drop(); |
| 2802 | 2802 |
| 2803 { VirtualFrame::RegisterAllocationScope scope(this); | 2803 { VirtualFrame::RegisterAllocationScope scope(this); |
| 2804 VisitStatements(node->catch_block()->statements()); | 2804 VisitStatements(node->catch_block()->statements()); |
| 2805 } | 2805 } |
| 2806 if (frame_ != NULL) { | 2806 if (frame_ != NULL) { |
| 2807 exit.Jump(); | 2807 exit.Jump(); |
| 2808 } | 2808 } |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3413 // introducing variables. In those cases, we do not want to | 3413 // introducing variables. In those cases, we do not want to |
| 3414 // perform a runtime call for all variables in the scope | 3414 // perform a runtime call for all variables in the scope |
| 3415 // containing the eval. | 3415 // containing the eval. |
| 3416 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | 3416 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { |
| 3417 LoadFromGlobalSlotCheckExtensions(slot, typeof_state, slow); | 3417 LoadFromGlobalSlotCheckExtensions(slot, typeof_state, slow); |
| 3418 frame_->SpillAll(); | 3418 frame_->SpillAll(); |
| 3419 done->Jump(); | 3419 done->Jump(); |
| 3420 | 3420 |
| 3421 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 3421 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
| 3422 frame_->SpillAll(); | 3422 frame_->SpillAll(); |
| 3423 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | 3423 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); |
| 3424 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); | 3424 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); |
| 3425 if (potential_slot != NULL) { | 3425 if (potential_slot != NULL) { |
| 3426 // Generate fast case for locals that rewrite to slots. | 3426 // Generate fast case for locals that rewrite to slots. |
| 3427 __ ldr(r0, | 3427 __ ldr(r0, |
| 3428 ContextSlotOperandCheckExtensions(potential_slot, | 3428 ContextSlotOperandCheckExtensions(potential_slot, |
| 3429 r1, | 3429 r1, |
| 3430 r2, | 3430 r2, |
| 3431 slow)); | 3431 slow)); |
| 3432 if (potential_slot->var()->mode() == Variable::CONST) { | 3432 if (potential_slot->var()->mode() == Variable::CONST) { |
| 3433 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3433 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 3434 __ cmp(r0, ip); | 3434 __ cmp(r0, ip); |
| 3435 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 3435 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
| 3436 } | 3436 } |
| 3437 done->Jump(); | 3437 done->Jump(); |
| 3438 } else if (rewrite != NULL) { | 3438 } else if (rewrite != NULL) { |
| 3439 // Generate fast case for argument loads. | 3439 // Generate fast case for argument loads. |
| 3440 Property* property = rewrite->AsProperty(); | 3440 Property* property = rewrite->AsProperty(); |
| 3441 if (property != NULL) { | 3441 if (property != NULL) { |
| 3442 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | 3442 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); |
| 3443 Literal* key_literal = property->key()->AsLiteral(); | 3443 Literal* key_literal = property->key()->AsLiteral(); |
| 3444 if (obj_proxy != NULL && | 3444 if (obj_proxy != NULL && |
| 3445 key_literal != NULL && | 3445 key_literal != NULL && |
| 3446 obj_proxy->IsArguments() && | 3446 obj_proxy->IsArguments() && |
| 3447 key_literal->handle()->IsSmi()) { | 3447 key_literal->handle()->IsSmi()) { |
| 3448 // Load arguments object if there are no eval-introduced | 3448 // Load arguments object if there are no eval-introduced |
| 3449 // variables. Then load the argument from the arguments | 3449 // variables. Then load the argument from the arguments |
| 3450 // object using keyed load. | 3450 // object using keyed load. |
| 3451 __ ldr(r0, | 3451 __ ldr(r0, |
| 3452 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | 3452 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
| 3453 r1, | 3453 r1, |
| 3454 r2, | 3454 r2, |
| 3455 slow)); | 3455 slow)); |
| 3456 frame_->EmitPush(r0); | 3456 frame_->EmitPush(r0); |
| 3457 __ mov(r1, Operand(key_literal->handle())); | 3457 __ mov(r1, Operand(key_literal->handle())); |
| 3458 frame_->EmitPush(r1); | 3458 frame_->EmitPush(r1); |
| 3459 EmitKeyedLoad(); | 3459 EmitKeyedLoad(); |
| 3460 done->Jump(); | 3460 done->Jump(); |
| 3461 } | 3461 } |
| 3462 } | 3462 } |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3728 } | 3728 } |
| 3729 | 3729 |
| 3730 | 3730 |
| 3731 void CodeGenerator::EmitSlotAssignment(Assignment* node) { | 3731 void CodeGenerator::EmitSlotAssignment(Assignment* node) { |
| 3732 #ifdef DEBUG | 3732 #ifdef DEBUG |
| 3733 int original_height = frame_->height(); | 3733 int original_height = frame_->height(); |
| 3734 #endif | 3734 #endif |
| 3735 Comment cmnt(masm(), "[ Variable Assignment"); | 3735 Comment cmnt(masm(), "[ Variable Assignment"); |
| 3736 Variable* var = node->target()->AsVariableProxy()->AsVariable(); | 3736 Variable* var = node->target()->AsVariableProxy()->AsVariable(); |
| 3737 ASSERT(var != NULL); | 3737 ASSERT(var != NULL); |
| 3738 Slot* slot = var->slot(); | 3738 Slot* slot = var->AsSlot(); |
| 3739 ASSERT(slot != NULL); | 3739 ASSERT(slot != NULL); |
| 3740 | 3740 |
| 3741 // Evaluate the right-hand side. | 3741 // Evaluate the right-hand side. |
| 3742 if (node->is_compound()) { | 3742 if (node->is_compound()) { |
| 3743 // For a compound assignment the right-hand side is a binary operation | 3743 // For a compound assignment the right-hand side is a binary operation |
| 3744 // between the current property value and the actual right-hand side. | 3744 // between the current property value and the actual right-hand side. |
| 3745 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 3745 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
| 3746 | 3746 |
| 3747 // Perform the binary operation. | 3747 // Perform the binary operation. |
| 3748 Literal* literal = node->value()->AsLiteral(); | 3748 Literal* literal = node->value()->AsLiteral(); |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4129 Load(args->at(i)); | 4129 Load(args->at(i)); |
| 4130 } | 4130 } |
| 4131 | 4131 |
| 4132 VirtualFrame::SpilledScope spilled_scope(frame_); | 4132 VirtualFrame::SpilledScope spilled_scope(frame_); |
| 4133 | 4133 |
| 4134 // If we know that eval can only be shadowed by eval-introduced | 4134 // If we know that eval can only be shadowed by eval-introduced |
| 4135 // variables we attempt to load the global eval function directly | 4135 // variables we attempt to load the global eval function directly |
| 4136 // in generated code. If we succeed, there is no need to perform a | 4136 // in generated code. If we succeed, there is no need to perform a |
| 4137 // context lookup in the runtime system. | 4137 // context lookup in the runtime system. |
| 4138 JumpTarget done; | 4138 JumpTarget done; |
| 4139 if (var->slot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { | 4139 if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { |
| 4140 ASSERT(var->slot()->type() == Slot::LOOKUP); | 4140 ASSERT(var->AsSlot()->type() == Slot::LOOKUP); |
| 4141 JumpTarget slow; | 4141 JumpTarget slow; |
| 4142 // Prepare the stack for the call to | 4142 // Prepare the stack for the call to |
| 4143 // ResolvePossiblyDirectEvalNoLookup by pushing the loaded | 4143 // ResolvePossiblyDirectEvalNoLookup by pushing the loaded |
| 4144 // function, the first argument to the eval call and the | 4144 // function, the first argument to the eval call and the |
| 4145 // receiver. | 4145 // receiver. |
| 4146 LoadFromGlobalSlotCheckExtensions(var->slot(), | 4146 LoadFromGlobalSlotCheckExtensions(var->AsSlot(), |
| 4147 NOT_INSIDE_TYPEOF, | 4147 NOT_INSIDE_TYPEOF, |
| 4148 &slow); | 4148 &slow); |
| 4149 frame_->EmitPush(r0); | 4149 frame_->EmitPush(r0); |
| 4150 if (arg_count > 0) { | 4150 if (arg_count > 0) { |
| 4151 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); | 4151 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); |
| 4152 frame_->EmitPush(r1); | 4152 frame_->EmitPush(r1); |
| 4153 } else { | 4153 } else { |
| 4154 frame_->EmitPush(r2); | 4154 frame_->EmitPush(r2); |
| 4155 } | 4155 } |
| 4156 __ ldr(r1, frame_->Receiver()); | 4156 __ ldr(r1, frame_->Receiver()); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4218 // Setup the name register and call the IC initialization code. | 4218 // Setup the name register and call the IC initialization code. |
| 4219 __ mov(r2, Operand(var->name())); | 4219 __ mov(r2, Operand(var->name())); |
| 4220 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 4220 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
| 4221 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); | 4221 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); |
| 4222 CodeForSourcePosition(node->position()); | 4222 CodeForSourcePosition(node->position()); |
| 4223 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, | 4223 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, |
| 4224 arg_count + 1); | 4224 arg_count + 1); |
| 4225 __ ldr(cp, frame_->Context()); | 4225 __ ldr(cp, frame_->Context()); |
| 4226 frame_->EmitPush(r0); | 4226 frame_->EmitPush(r0); |
| 4227 | 4227 |
| 4228 } else if (var != NULL && var->slot() != NULL && | 4228 } else if (var != NULL && var->AsSlot() != NULL && |
| 4229 var->slot()->type() == Slot::LOOKUP) { | 4229 var->AsSlot()->type() == Slot::LOOKUP) { |
| 4230 // ---------------------------------- | 4230 // ---------------------------------- |
| 4231 // JavaScript examples: | 4231 // JavaScript examples: |
| 4232 // | 4232 // |
| 4233 // with (obj) foo(1, 2, 3) // foo may be in obj. | 4233 // with (obj) foo(1, 2, 3) // foo may be in obj. |
| 4234 // | 4234 // |
| 4235 // function f() {}; | 4235 // function f() {}; |
| 4236 // function g() { | 4236 // function g() { |
| 4237 // eval(...); | 4237 // eval(...); |
| 4238 // f(); // f could be in extension object. | 4238 // f(); // f could be in extension object. |
| 4239 // } | 4239 // } |
| 4240 // ---------------------------------- | 4240 // ---------------------------------- |
| 4241 | 4241 |
| 4242 JumpTarget slow, done; | 4242 JumpTarget slow, done; |
| 4243 | 4243 |
| 4244 // Generate fast case for loading functions from slots that | 4244 // Generate fast case for loading functions from slots that |
| 4245 // correspond to local/global variables or arguments unless they | 4245 // correspond to local/global variables or arguments unless they |
| 4246 // are shadowed by eval-introduced bindings. | 4246 // are shadowed by eval-introduced bindings. |
| 4247 EmitDynamicLoadFromSlotFastCase(var->slot(), | 4247 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), |
| 4248 NOT_INSIDE_TYPEOF, | 4248 NOT_INSIDE_TYPEOF, |
| 4249 &slow, | 4249 &slow, |
| 4250 &done); | 4250 &done); |
| 4251 | 4251 |
| 4252 slow.Bind(); | 4252 slow.Bind(); |
| 4253 // Load the function | 4253 // Load the function |
| 4254 frame_->EmitPush(cp); | 4254 frame_->EmitPush(cp); |
| 4255 frame_->EmitPush(Operand(var->name())); | 4255 frame_->EmitPush(Operand(var->name())); |
| 4256 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); | 4256 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); |
| 4257 // r0: slot value; r1: receiver | 4257 // r0: slot value; r1: receiver |
| (...skipping 1663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5921 } else if (op == Token::DELETE) { | 5921 } else if (op == Token::DELETE) { |
| 5922 Property* property = node->expression()->AsProperty(); | 5922 Property* property = node->expression()->AsProperty(); |
| 5923 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); | 5923 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
| 5924 if (property != NULL) { | 5924 if (property != NULL) { |
| 5925 Load(property->obj()); | 5925 Load(property->obj()); |
| 5926 Load(property->key()); | 5926 Load(property->key()); |
| 5927 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); | 5927 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); |
| 5928 frame_->EmitPush(r0); | 5928 frame_->EmitPush(r0); |
| 5929 | 5929 |
| 5930 } else if (variable != NULL) { | 5930 } else if (variable != NULL) { |
| 5931 Slot* slot = variable->slot(); | 5931 Slot* slot = variable->AsSlot(); |
| 5932 if (variable->is_global()) { | 5932 if (variable->is_global()) { |
| 5933 LoadGlobal(); | 5933 LoadGlobal(); |
| 5934 frame_->EmitPush(Operand(variable->name())); | 5934 frame_->EmitPush(Operand(variable->name())); |
| 5935 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); | 5935 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); |
| 5936 frame_->EmitPush(r0); | 5936 frame_->EmitPush(r0); |
| 5937 | 5937 |
| 5938 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 5938 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 5939 // lookup the context holding the named variable | 5939 // lookup the context holding the named variable |
| 5940 frame_->EmitPush(cp); | 5940 frame_->EmitPush(cp); |
| 5941 frame_->EmitPush(Operand(variable->name())); | 5941 frame_->EmitPush(Operand(variable->name())); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6055 Comment cmnt(masm_, "[ CountOperation"); | 6055 Comment cmnt(masm_, "[ CountOperation"); |
| 6056 VirtualFrame::RegisterAllocationScope scope(this); | 6056 VirtualFrame::RegisterAllocationScope scope(this); |
| 6057 | 6057 |
| 6058 bool is_postfix = node->is_postfix(); | 6058 bool is_postfix = node->is_postfix(); |
| 6059 bool is_increment = node->op() == Token::INC; | 6059 bool is_increment = node->op() == Token::INC; |
| 6060 | 6060 |
| 6061 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); | 6061 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); |
| 6062 bool is_const = (var != NULL && var->mode() == Variable::CONST); | 6062 bool is_const = (var != NULL && var->mode() == Variable::CONST); |
| 6063 bool is_slot = (var != NULL && var->mode() == Variable::VAR); | 6063 bool is_slot = (var != NULL && var->mode() == Variable::VAR); |
| 6064 | 6064 |
| 6065 if (!is_const && is_slot && type_info(var->slot()).IsSmi()) { | 6065 if (!is_const && is_slot && type_info(var->AsSlot()).IsSmi()) { |
| 6066 // The type info declares that this variable is always a Smi. That | 6066 // The type info declares that this variable is always a Smi. That |
| 6067 // means it is a Smi both before and after the increment/decrement. | 6067 // means it is a Smi both before and after the increment/decrement. |
| 6068 // Lets make use of that to make a very minimal count. | 6068 // Lets make use of that to make a very minimal count. |
| 6069 Reference target(this, node->expression(), !is_const); | 6069 Reference target(this, node->expression(), !is_const); |
| 6070 ASSERT(!target.is_illegal()); | 6070 ASSERT(!target.is_illegal()); |
| 6071 target.GetValue(); // Pushes the value. | 6071 target.GetValue(); // Pushes the value. |
| 6072 Register value = frame_->PopToRegister(); | 6072 Register value = frame_->PopToRegister(); |
| 6073 if (is_postfix) frame_->EmitPush(value); | 6073 if (is_postfix) frame_->EmitPush(value); |
| 6074 if (is_increment) { | 6074 if (is_increment) { |
| 6075 __ add(value, value, Operand(Smi::FromInt(1))); | 6075 __ add(value, value, Operand(Smi::FromInt(1))); |
| (...skipping 1124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7200 ASSERT(!cgen_->has_cc()); | 7200 ASSERT(!cgen_->has_cc()); |
| 7201 MacroAssembler* masm = cgen_->masm(); | 7201 MacroAssembler* masm = cgen_->masm(); |
| 7202 Property* property = expression_->AsProperty(); | 7202 Property* property = expression_->AsProperty(); |
| 7203 if (property != NULL) { | 7203 if (property != NULL) { |
| 7204 cgen_->CodeForSourcePosition(property->position()); | 7204 cgen_->CodeForSourcePosition(property->position()); |
| 7205 } | 7205 } |
| 7206 | 7206 |
| 7207 switch (type_) { | 7207 switch (type_) { |
| 7208 case SLOT: { | 7208 case SLOT: { |
| 7209 Comment cmnt(masm, "[ Load from Slot"); | 7209 Comment cmnt(masm, "[ Load from Slot"); |
| 7210 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 7210 Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot(); |
| 7211 ASSERT(slot != NULL); | 7211 ASSERT(slot != NULL); |
| 7212 DupIfPersist(); | 7212 DupIfPersist(); |
| 7213 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 7213 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
| 7214 break; | 7214 break; |
| 7215 } | 7215 } |
| 7216 | 7216 |
| 7217 case NAMED: { | 7217 case NAMED: { |
| 7218 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 7218 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
| 7219 bool is_global = var != NULL; | 7219 bool is_global = var != NULL; |
| 7220 ASSERT(!is_global || var->is_global()); | 7220 ASSERT(!is_global || var->is_global()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 7244 MacroAssembler* masm = cgen_->masm(); | 7244 MacroAssembler* masm = cgen_->masm(); |
| 7245 VirtualFrame* frame = cgen_->frame(); | 7245 VirtualFrame* frame = cgen_->frame(); |
| 7246 Property* property = expression_->AsProperty(); | 7246 Property* property = expression_->AsProperty(); |
| 7247 if (property != NULL) { | 7247 if (property != NULL) { |
| 7248 cgen_->CodeForSourcePosition(property->position()); | 7248 cgen_->CodeForSourcePosition(property->position()); |
| 7249 } | 7249 } |
| 7250 | 7250 |
| 7251 switch (type_) { | 7251 switch (type_) { |
| 7252 case SLOT: { | 7252 case SLOT: { |
| 7253 Comment cmnt(masm, "[ Store to Slot"); | 7253 Comment cmnt(masm, "[ Store to Slot"); |
| 7254 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 7254 Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot(); |
| 7255 cgen_->StoreToSlot(slot, init_state); | 7255 cgen_->StoreToSlot(slot, init_state); |
| 7256 set_unloaded(); | 7256 set_unloaded(); |
| 7257 break; | 7257 break; |
| 7258 } | 7258 } |
| 7259 | 7259 |
| 7260 case NAMED: { | 7260 case NAMED: { |
| 7261 Comment cmnt(masm, "[ Store to named Property"); | 7261 Comment cmnt(masm, "[ Store to named Property"); |
| 7262 cgen_->EmitNamedStore(GetName(), false); | 7262 cgen_->EmitNamedStore(GetName(), false); |
| 7263 frame->EmitPush(r0); | 7263 frame->EmitPush(r0); |
| 7264 set_unloaded(); | 7264 set_unloaded(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7304 BinaryOpIC::GetName(runtime_operands_type_)); | 7304 BinaryOpIC::GetName(runtime_operands_type_)); |
| 7305 return name_; | 7305 return name_; |
| 7306 } | 7306 } |
| 7307 | 7307 |
| 7308 | 7308 |
| 7309 #undef __ | 7309 #undef __ |
| 7310 | 7310 |
| 7311 } } // namespace v8::internal | 7311 } } // namespace v8::internal |
| 7312 | 7312 |
| 7313 #endif // V8_TARGET_ARCH_ARM | 7313 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |