OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 1018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 } | 1029 } |
1030 __ orr(r2, r0, Operand(r1)); | 1030 __ orr(r2, r0, Operand(r1)); |
1031 __ tst(r2, Operand(kSmiTagMask)); | 1031 __ tst(r2, Operand(kSmiTagMask)); |
1032 smi.Branch(eq); | 1032 smi.Branch(eq); |
1033 | 1033 |
1034 // Perform non-smi comparison by stub. | 1034 // Perform non-smi comparison by stub. |
1035 // CompareStub takes arguments in r0 and r1, returns <0, >0 or 0 in r0. | 1035 // CompareStub takes arguments in r0 and r1, returns <0, >0 or 0 in r0. |
1036 // We call with 0 args because there are 0 on the stack. | 1036 // We call with 0 args because there are 0 on the stack. |
1037 CompareStub stub(cc, strict); | 1037 CompareStub stub(cc, strict); |
1038 frame_->CallStub(&stub, 0); | 1038 frame_->CallStub(&stub, 0); |
1039 | 1039 __ cmp(r0, Operand(0)); |
1040 Result result = allocator_->Allocate(r0); | |
1041 ASSERT(result.is_valid()); | |
1042 __ cmp(result.reg(), Operand(0)); | |
1043 result.Unuse(); | |
1044 exit.Jump(); | 1040 exit.Jump(); |
1045 | 1041 |
1046 // Do smi comparisons by pointer comparison. | 1042 // Do smi comparisons by pointer comparison. |
1047 smi.Bind(); | 1043 smi.Bind(); |
1048 __ cmp(r1, Operand(r0)); | 1044 __ cmp(r1, Operand(r0)); |
1049 | 1045 |
1050 exit.Bind(); | 1046 exit.Bind(); |
1051 cc_reg_ = cc; | 1047 cc_reg_ = cc; |
1052 } | 1048 } |
1053 | 1049 |
(...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1742 // [Object] | 1738 // [Object] |
1743 | 1739 |
1744 // Check if enumerable is already a JSObject | 1740 // Check if enumerable is already a JSObject |
1745 __ tst(r0, Operand(kSmiTagMask)); | 1741 __ tst(r0, Operand(kSmiTagMask)); |
1746 primitive.Branch(eq); | 1742 primitive.Branch(eq); |
1747 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); | 1743 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); |
1748 jsobject.Branch(hs); | 1744 jsobject.Branch(hs); |
1749 | 1745 |
1750 primitive.Bind(); | 1746 primitive.Bind(); |
1751 frame_->EmitPush(r0); | 1747 frame_->EmitPush(r0); |
1752 Result arg_count = allocator_->Allocate(r0); | 1748 Result arg_count(r0); |
1753 ASSERT(arg_count.is_valid()); | 1749 __ mov(r0, Operand(0)); |
1754 __ mov(arg_count.reg(), Operand(0)); | |
1755 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, &arg_count, 1); | 1750 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, &arg_count, 1); |
1756 | 1751 |
1757 jsobject.Bind(); | 1752 jsobject.Bind(); |
1758 // Get the set of properties (as a FixedArray or Map). | 1753 // Get the set of properties (as a FixedArray or Map). |
1759 frame_->EmitPush(r0); // duplicate the object being enumerated | 1754 frame_->EmitPush(r0); // duplicate the object being enumerated |
1760 frame_->EmitPush(r0); | 1755 frame_->EmitPush(r0); |
1761 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 1756 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1); |
1762 | 1757 |
1763 // If we got a Map, we can do a fast modification check. | 1758 // If we got a Map, we can do a fast modification check. |
1764 // Otherwise, we got a FixedArray, and we have to do a slow check. | 1759 // Otherwise, we got a FixedArray, and we have to do a slow check. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1825 // If not, we have to filter the key. | 1820 // If not, we have to filter the key. |
1826 __ ldr(r1, frame_->ElementAt(4)); | 1821 __ ldr(r1, frame_->ElementAt(4)); |
1827 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); | 1822 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); |
1828 __ cmp(r1, Operand(r2)); | 1823 __ cmp(r1, Operand(r2)); |
1829 end_del_check.Branch(eq); | 1824 end_del_check.Branch(eq); |
1830 | 1825 |
1831 // Convert the entry to a string (or null if it isn't a property anymore). | 1826 // Convert the entry to a string (or null if it isn't a property anymore). |
1832 __ ldr(r0, frame_->ElementAt(4)); // push enumerable | 1827 __ ldr(r0, frame_->ElementAt(4)); // push enumerable |
1833 frame_->EmitPush(r0); | 1828 frame_->EmitPush(r0); |
1834 frame_->EmitPush(r3); // push entry | 1829 frame_->EmitPush(r3); // push entry |
1835 Result arg_count_register = allocator_->Allocate(r0); | 1830 Result arg_count_reg(r0); |
1836 ASSERT(arg_count_register.is_valid()); | 1831 __ mov(r0, Operand(1)); |
1837 __ mov(arg_count_register.reg(), Operand(1)); | 1832 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS, &arg_count_reg, 2); |
1838 Result result = frame_->InvokeBuiltin(Builtins::FILTER_KEY, | 1833 __ mov(r3, Operand(r0)); |
1839 CALL_JS, | |
1840 &arg_count_register, | |
1841 2); | |
1842 __ mov(r3, Operand(result.reg())); | |
1843 result.Unuse(); | |
1844 | 1834 |
1845 // If the property has been removed while iterating, we just skip it. | 1835 // If the property has been removed while iterating, we just skip it. |
1846 __ cmp(r3, Operand(Factory::null_value())); | 1836 __ cmp(r3, Operand(Factory::null_value())); |
1847 node->continue_target()->Branch(eq); | 1837 node->continue_target()->Branch(eq); |
1848 | 1838 |
1849 end_del_check.Bind(); | 1839 end_del_check.Bind(); |
1850 // Store the entry in the 'each' expression and take another spin in the | 1840 // Store the entry in the 'each' expression and take another spin in the |
1851 // loop. r3: i'th entry of the enum cache (or string there of) | 1841 // loop. r3: i'th entry of the enum cache (or string there of) |
1852 frame_->EmitPush(r3); // push entry | 1842 frame_->EmitPush(r3); // push entry |
1853 { Reference each(this, node->each()); | 1843 { Reference each(this, node->each()); |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2426 __ b(&next); | 2416 __ b(&next); |
2427 __ bind(&fast); | 2417 __ bind(&fast); |
2428 } | 2418 } |
2429 | 2419 |
2430 // All extension objects were empty and it is safe to use a global | 2420 // All extension objects were empty and it is safe to use a global |
2431 // load IC call. | 2421 // load IC call. |
2432 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 2422 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
2433 // Load the global object. | 2423 // Load the global object. |
2434 LoadGlobal(); | 2424 LoadGlobal(); |
2435 // Setup the name register. | 2425 // Setup the name register. |
2436 Result name = allocator_->Allocate(r2); | 2426 Result name(r2); |
2437 ASSERT(name.is_valid()); // We are in spilled code. | 2427 __ mov(r2, Operand(slot->var()->name())); |
2438 __ mov(name.reg(), Operand(slot->var()->name())); | |
2439 // Call IC stub. | 2428 // Call IC stub. |
2440 if (typeof_state == INSIDE_TYPEOF) { | 2429 if (typeof_state == INSIDE_TYPEOF) { |
2441 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, &name, 0); | 2430 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, &name, 0); |
2442 } else { | 2431 } else { |
2443 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, &name, 0); | 2432 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, &name, 0); |
2444 } | 2433 } |
2445 | 2434 |
2446 // Drop the global object. The result is in r0. | 2435 // Drop the global object. The result is in r0. |
2447 frame_->Drop(); | 2436 frame_->Drop(); |
2448 } | 2437 } |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2768 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { | 2757 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { |
2769 #ifdef DEBUG | 2758 #ifdef DEBUG |
2770 int original_height = frame_->height(); | 2759 int original_height = frame_->height(); |
2771 #endif | 2760 #endif |
2772 VirtualFrame::SpilledScope spilled_scope; | 2761 VirtualFrame::SpilledScope spilled_scope; |
2773 // Call runtime routine to allocate the catch extension object and | 2762 // Call runtime routine to allocate the catch extension object and |
2774 // assign the exception value to the catch variable. | 2763 // assign the exception value to the catch variable. |
2775 Comment cmnt(masm_, "[ CatchExtensionObject"); | 2764 Comment cmnt(masm_, "[ CatchExtensionObject"); |
2776 LoadAndSpill(node->key()); | 2765 LoadAndSpill(node->key()); |
2777 LoadAndSpill(node->value()); | 2766 LoadAndSpill(node->value()); |
2778 Result result = | 2767 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2); |
2779 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2); | 2768 frame_->EmitPush(r0); |
2780 frame_->EmitPush(result.reg()); | |
2781 ASSERT(frame_->height() == original_height + 1); | 2769 ASSERT(frame_->height() == original_height + 1); |
2782 } | 2770 } |
2783 | 2771 |
2784 | 2772 |
2785 void CodeGenerator::VisitAssignment(Assignment* node) { | 2773 void CodeGenerator::VisitAssignment(Assignment* node) { |
2786 #ifdef DEBUG | 2774 #ifdef DEBUG |
2787 int original_height = frame_->height(); | 2775 int original_height = frame_->height(); |
2788 #endif | 2776 #endif |
2789 VirtualFrame::SpilledScope spilled_scope; | 2777 VirtualFrame::SpilledScope spilled_scope; |
2790 Comment cmnt(masm_, "[ Assignment"); | 2778 Comment cmnt(masm_, "[ Assignment"); |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3110 LoadGlobal(); | 3098 LoadGlobal(); |
3111 | 3099 |
3112 // Push the arguments ("left-to-right") on the stack. | 3100 // Push the arguments ("left-to-right") on the stack. |
3113 ZoneList<Expression*>* args = node->arguments(); | 3101 ZoneList<Expression*>* args = node->arguments(); |
3114 int arg_count = args->length(); | 3102 int arg_count = args->length(); |
3115 for (int i = 0; i < arg_count; i++) { | 3103 for (int i = 0; i < arg_count; i++) { |
3116 LoadAndSpill(args->at(i)); | 3104 LoadAndSpill(args->at(i)); |
3117 } | 3105 } |
3118 | 3106 |
3119 // r0: the number of arguments. | 3107 // r0: the number of arguments. |
3120 Result num_args = allocator_->Allocate(r0); | 3108 Result num_args(r0); |
3121 ASSERT(num_args.is_valid()); | 3109 __ mov(r0, Operand(arg_count)); |
3122 __ mov(num_args.reg(), Operand(arg_count)); | |
3123 | 3110 |
3124 // Load the function into r1 as per calling convention. | 3111 // Load the function into r1 as per calling convention. |
3125 Result function = allocator_->Allocate(r1); | 3112 Result function(r1); |
3126 ASSERT(function.is_valid()); | 3113 __ ldr(r1, frame_->ElementAt(arg_count + 1)); |
3127 __ ldr(function.reg(), frame_->ElementAt(arg_count + 1)); | |
3128 | 3114 |
3129 // Call the construct call builtin that handles allocation and | 3115 // Call the construct call builtin that handles allocation and |
3130 // constructor invocation. | 3116 // constructor invocation. |
3131 CodeForSourcePosition(node->position()); | 3117 CodeForSourcePosition(node->position()); |
3132 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); | 3118 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); |
3133 Result result = frame_->CallCodeObject(ic, | 3119 frame_->CallCodeObject(ic, |
3134 RelocInfo::CONSTRUCT_CALL, | 3120 RelocInfo::CONSTRUCT_CALL, |
3135 &num_args, | 3121 &num_args, |
3136 &function, | 3122 &function, |
3137 arg_count + 1); | 3123 arg_count + 1); |
3138 | 3124 |
3139 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). | 3125 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). |
3140 __ str(r0, frame_->Top()); | 3126 __ str(r0, frame_->Top()); |
3141 ASSERT(frame_->height() == original_height + 1); | 3127 ASSERT(frame_->height() == original_height + 1); |
3142 } | 3128 } |
3143 | 3129 |
3144 | 3130 |
3145 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { | 3131 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
3146 VirtualFrame::SpilledScope spilled_scope; | 3132 VirtualFrame::SpilledScope spilled_scope; |
3147 ASSERT(args->length() == 1); | 3133 ASSERT(args->length() == 1); |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3470 // LoadCondition may (and usually does) leave a test and branch to | 3456 // LoadCondition may (and usually does) leave a test and branch to |
3471 // be emitted by the caller. In that case, negate the condition. | 3457 // be emitted by the caller. In that case, negate the condition. |
3472 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); | 3458 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); |
3473 | 3459 |
3474 } else if (op == Token::DELETE) { | 3460 } else if (op == Token::DELETE) { |
3475 Property* property = node->expression()->AsProperty(); | 3461 Property* property = node->expression()->AsProperty(); |
3476 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); | 3462 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
3477 if (property != NULL) { | 3463 if (property != NULL) { |
3478 LoadAndSpill(property->obj()); | 3464 LoadAndSpill(property->obj()); |
3479 LoadAndSpill(property->key()); | 3465 LoadAndSpill(property->key()); |
3480 Result arg_count = allocator_->Allocate(r0); | 3466 Result arg_count(r0); |
3481 ASSERT(arg_count.is_valid()); | 3467 __ mov(r0, Operand(1)); // not counting receiver |
3482 __ mov(arg_count.reg(), Operand(1)); // not counting receiver | |
3483 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2); | 3468 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2); |
3484 | 3469 |
3485 } else if (variable != NULL) { | 3470 } else if (variable != NULL) { |
3486 Slot* slot = variable->slot(); | 3471 Slot* slot = variable->slot(); |
3487 if (variable->is_global()) { | 3472 if (variable->is_global()) { |
3488 LoadGlobal(); | 3473 LoadGlobal(); |
3489 __ mov(r0, Operand(variable->name())); | 3474 __ mov(r0, Operand(variable->name())); |
3490 frame_->EmitPush(r0); | 3475 frame_->EmitPush(r0); |
3491 Result arg_count = allocator_->Allocate(r0); | 3476 Result arg_count(r0); |
3492 ASSERT(arg_count.is_valid()); | 3477 __ mov(r0, Operand(1)); // not counting receiver |
3493 __ mov(arg_count.reg(), Operand(1)); // not counting receiver | |
3494 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2); | 3478 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2); |
3495 | 3479 |
3496 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 3480 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
3497 // lookup the context holding the named variable | 3481 // lookup the context holding the named variable |
3498 frame_->EmitPush(cp); | 3482 frame_->EmitPush(cp); |
3499 __ mov(r0, Operand(variable->name())); | 3483 __ mov(r0, Operand(variable->name())); |
3500 frame_->EmitPush(r0); | 3484 frame_->EmitPush(r0); |
3501 frame_->CallRuntime(Runtime::kLookupContext, 2); | 3485 frame_->CallRuntime(Runtime::kLookupContext, 2); |
3502 // r0: context | 3486 // r0: context |
3503 frame_->EmitPush(r0); | 3487 frame_->EmitPush(r0); |
3504 __ mov(r0, Operand(variable->name())); | 3488 __ mov(r0, Operand(variable->name())); |
3505 frame_->EmitPush(r0); | 3489 frame_->EmitPush(r0); |
3506 Result arg_count = allocator_->Allocate(r0); | 3490 Result arg_count(r0); |
3507 ASSERT(arg_count.is_valid()); | 3491 __ mov(r0, Operand(1)); // not counting receiver |
3508 __ mov(arg_count.reg(), Operand(1)); // not counting receiver | |
3509 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2); | 3492 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2); |
3510 | 3493 |
3511 } else { | 3494 } else { |
3512 // Default: Result of deleting non-global, not dynamically | 3495 // Default: Result of deleting non-global, not dynamically |
3513 // introduced variables is false. | 3496 // introduced variables is false. |
3514 __ mov(r0, Operand(Factory::false_value())); | 3497 __ mov(r0, Operand(Factory::false_value())); |
3515 } | 3498 } |
3516 | 3499 |
3517 } else { | 3500 } else { |
3518 // Default: Result of deleting expressions is true. | 3501 // Default: Result of deleting expressions is true. |
(...skipping 30 matching lines...) Expand all Loading... |
3549 } | 3532 } |
3550 | 3533 |
3551 case Token::BIT_NOT: { | 3534 case Token::BIT_NOT: { |
3552 // smi check | 3535 // smi check |
3553 JumpTarget smi_label; | 3536 JumpTarget smi_label; |
3554 JumpTarget continue_label; | 3537 JumpTarget continue_label; |
3555 __ tst(r0, Operand(kSmiTagMask)); | 3538 __ tst(r0, Operand(kSmiTagMask)); |
3556 smi_label.Branch(eq); | 3539 smi_label.Branch(eq); |
3557 | 3540 |
3558 frame_->EmitPush(r0); | 3541 frame_->EmitPush(r0); |
3559 Result arg_count = allocator_->Allocate(r0); | 3542 Result arg_count(r0); |
3560 ASSERT(arg_count.is_valid()); | 3543 __ mov(r0, Operand(0)); // not counting receiver |
3561 __ mov(arg_count.reg(), Operand(0)); // not counting receiver | |
3562 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, &arg_count, 1); | 3544 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, &arg_count, 1); |
3563 | 3545 |
3564 continue_label.Jump(); | 3546 continue_label.Jump(); |
3565 smi_label.Bind(); | 3547 smi_label.Bind(); |
3566 __ mvn(r0, Operand(r0)); | 3548 __ mvn(r0, Operand(r0)); |
3567 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag | 3549 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag |
3568 continue_label.Bind(); | 3550 continue_label.Bind(); |
3569 break; | 3551 break; |
3570 } | 3552 } |
3571 | 3553 |
3572 case Token::VOID: | 3554 case Token::VOID: |
3573 // since the stack top is cached in r0, popping and then | 3555 // since the stack top is cached in r0, popping and then |
3574 // pushing a value can be done by just writing to r0. | 3556 // pushing a value can be done by just writing to r0. |
3575 __ mov(r0, Operand(Factory::undefined_value())); | 3557 __ mov(r0, Operand(Factory::undefined_value())); |
3576 break; | 3558 break; |
3577 | 3559 |
3578 case Token::ADD: { | 3560 case Token::ADD: { |
3579 // Smi check. | 3561 // Smi check. |
3580 JumpTarget continue_label; | 3562 JumpTarget continue_label; |
3581 __ tst(r0, Operand(kSmiTagMask)); | 3563 __ tst(r0, Operand(kSmiTagMask)); |
3582 continue_label.Branch(eq); | 3564 continue_label.Branch(eq); |
3583 frame_->EmitPush(r0); | 3565 frame_->EmitPush(r0); |
3584 Result arg_count = allocator_->Allocate(r0); | 3566 Result arg_count(r0); |
3585 ASSERT(arg_count.is_valid()); | 3567 __ mov(r0, Operand(0)); // not counting receiver |
3586 __ mov(arg_count.reg(), Operand(0)); // not counting receiver | |
3587 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); | 3568 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); |
3588 continue_label.Bind(); | 3569 continue_label.Bind(); |
3589 break; | 3570 break; |
3590 } | 3571 } |
3591 default: | 3572 default: |
3592 UNREACHABLE(); | 3573 UNREACHABLE(); |
3593 } | 3574 } |
3594 frame_->EmitPush(r0); // r0 has result | 3575 frame_->EmitPush(r0); // r0 has result |
3595 } | 3576 } |
3596 ASSERT(!has_valid_frame() || | 3577 ASSERT(!has_valid_frame() || |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3662 __ sub(r0, r0, Operand(r1)); | 3643 __ sub(r0, r0, Operand(r1)); |
3663 } else { | 3644 } else { |
3664 __ add(r0, r0, Operand(r1)); | 3645 __ add(r0, r0, Operand(r1)); |
3665 } | 3646 } |
3666 | 3647 |
3667 // Slow case: Convert to number. | 3648 // Slow case: Convert to number. |
3668 slow.Bind(); | 3649 slow.Bind(); |
3669 { | 3650 { |
3670 // Convert the operand to a number. | 3651 // Convert the operand to a number. |
3671 frame_->EmitPush(r0); | 3652 frame_->EmitPush(r0); |
3672 Result arg_count = allocator_->Allocate(r0); | 3653 Result arg_count(r0); |
3673 ASSERT(arg_count.is_valid()); | 3654 __ mov(r0, Operand(0)); |
3674 __ mov(arg_count.reg(), Operand(0)); | |
3675 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); | 3655 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); |
3676 } | 3656 } |
3677 if (is_postfix) { | 3657 if (is_postfix) { |
3678 // Postfix: store to result (on the stack). | 3658 // Postfix: store to result (on the stack). |
3679 __ str(r0, frame_->ElementAt(target.size())); | 3659 __ str(r0, frame_->ElementAt(target.size())); |
3680 } | 3660 } |
3681 | 3661 |
3682 // Compute the new value. | 3662 // Compute the new value. |
3683 __ mov(r1, Operand(Smi::FromInt(1))); | 3663 __ mov(r1, Operand(Smi::FromInt(1))); |
3684 frame_->EmitPush(r0); | 3664 frame_->EmitPush(r0); |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4041 Comparison(ge, left, right); | 4021 Comparison(ge, left, right); |
4042 break; | 4022 break; |
4043 | 4023 |
4044 case Token::EQ_STRICT: | 4024 case Token::EQ_STRICT: |
4045 Comparison(eq, left, right, true); | 4025 Comparison(eq, left, right, true); |
4046 break; | 4026 break; |
4047 | 4027 |
4048 case Token::IN: { | 4028 case Token::IN: { |
4049 LoadAndSpill(left); | 4029 LoadAndSpill(left); |
4050 LoadAndSpill(right); | 4030 LoadAndSpill(right); |
4051 Result arg_count = allocator_->Allocate(r0); | 4031 Result arg_count(r0); |
4052 ASSERT(arg_count.is_valid()); | 4032 __ mov(r0, Operand(1)); // not counting receiver |
4053 __ mov(arg_count.reg(), Operand(1)); // not counting receiver | 4033 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, &arg_count, 2); |
4054 Result result = frame_->InvokeBuiltin(Builtins::IN, | 4034 frame_->EmitPush(r0); |
4055 CALL_JS, | |
4056 &arg_count, | |
4057 2); | |
4058 frame_->EmitPush(result.reg()); | |
4059 break; | 4035 break; |
4060 } | 4036 } |
4061 | 4037 |
4062 case Token::INSTANCEOF: { | 4038 case Token::INSTANCEOF: { |
4063 LoadAndSpill(left); | 4039 LoadAndSpill(left); |
4064 LoadAndSpill(right); | 4040 LoadAndSpill(right); |
4065 InstanceofStub stub; | 4041 InstanceofStub stub; |
4066 Result result = frame_->CallStub(&stub, 2); | 4042 frame_->CallStub(&stub, 2); |
4067 // At this point if instanceof succeeded then r0 == 0. | 4043 // At this point if instanceof succeeded then r0 == 0. |
4068 __ tst(result.reg(), Operand(result.reg())); | 4044 __ tst(r0, Operand(r0)); |
4069 cc_reg_ = eq; | 4045 cc_reg_ = eq; |
4070 break; | 4046 break; |
4071 } | 4047 } |
4072 | 4048 |
4073 default: | 4049 default: |
4074 UNREACHABLE(); | 4050 UNREACHABLE(); |
4075 } | 4051 } |
4076 ASSERT((has_cc() && frame_->height() == original_height) || | 4052 ASSERT((has_cc() && frame_->height() == original_height) || |
4077 (!has_cc() && frame_->height() == original_height + 1)); | 4053 (!has_cc() && frame_->height() == original_height + 1)); |
4078 } | 4054 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4128 // distinction between expressions in a typeof and not in a typeof. If | 4104 // distinction between expressions in a typeof and not in a typeof. If |
4129 // there is a chance that reference errors can be thrown below, we | 4105 // there is a chance that reference errors can be thrown below, we |
4130 // must distinguish between the two kinds of loads (typeof expression | 4106 // must distinguish between the two kinds of loads (typeof expression |
4131 // loads must not throw a reference error). | 4107 // loads must not throw a reference error). |
4132 VirtualFrame* frame = cgen_->frame(); | 4108 VirtualFrame* frame = cgen_->frame(); |
4133 Comment cmnt(masm, "[ Load from named Property"); | 4109 Comment cmnt(masm, "[ Load from named Property"); |
4134 Handle<String> name(GetName()); | 4110 Handle<String> name(GetName()); |
4135 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 4111 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
4136 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 4112 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
4137 // Setup the name register. | 4113 // Setup the name register. |
4138 Result name_reg = cgen_->allocator()->Allocate(r2); | 4114 Result name_reg(r2); |
4139 ASSERT(name_reg.is_valid()); | 4115 __ mov(r2, Operand(name)); |
4140 __ mov(name_reg.reg(), Operand(name)); | |
4141 ASSERT(var == NULL || var->is_global()); | 4116 ASSERT(var == NULL || var->is_global()); |
4142 RelocInfo::Mode rmode = (var == NULL) | 4117 RelocInfo::Mode rmode = (var == NULL) |
4143 ? RelocInfo::CODE_TARGET | 4118 ? RelocInfo::CODE_TARGET |
4144 : RelocInfo::CODE_TARGET_CONTEXT; | 4119 : RelocInfo::CODE_TARGET_CONTEXT; |
4145 Result answer = frame->CallCodeObject(ic, rmode, &name_reg, 0); | 4120 frame->CallCodeObject(ic, rmode, &name_reg, 0); |
4146 frame->EmitPush(answer.reg()); | 4121 frame->EmitPush(r0); |
4147 break; | 4122 break; |
4148 } | 4123 } |
4149 | 4124 |
4150 case KEYED: { | 4125 case KEYED: { |
4151 // TODO(1241834): Make sure that this it is safe to ignore the | 4126 // TODO(1241834): Make sure that this it is safe to ignore the |
4152 // distinction between expressions in a typeof and not in a typeof. | 4127 // distinction between expressions in a typeof and not in a typeof. |
4153 | 4128 |
4154 // TODO(181): Implement inlined version of array indexing once | 4129 // TODO(181): Implement inlined version of array indexing once |
4155 // loop nesting is properly tracked on ARM. | 4130 // loop nesting is properly tracked on ARM. |
4156 VirtualFrame* frame = cgen_->frame(); | 4131 VirtualFrame* frame = cgen_->frame(); |
4157 Comment cmnt(masm, "[ Load from keyed Property"); | 4132 Comment cmnt(masm, "[ Load from keyed Property"); |
4158 ASSERT(property != NULL); | 4133 ASSERT(property != NULL); |
4159 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 4134 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
4160 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 4135 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
4161 ASSERT(var == NULL || var->is_global()); | 4136 ASSERT(var == NULL || var->is_global()); |
4162 RelocInfo::Mode rmode = (var == NULL) | 4137 RelocInfo::Mode rmode = (var == NULL) |
4163 ? RelocInfo::CODE_TARGET | 4138 ? RelocInfo::CODE_TARGET |
4164 : RelocInfo::CODE_TARGET_CONTEXT; | 4139 : RelocInfo::CODE_TARGET_CONTEXT; |
4165 Result answer = frame->CallCodeObject(ic, rmode, 0); | 4140 frame->CallCodeObject(ic, rmode, 0); |
4166 frame->EmitPush(answer.reg()); | 4141 frame->EmitPush(r0); |
4167 break; | 4142 break; |
4168 } | 4143 } |
4169 | 4144 |
4170 default: | 4145 default: |
4171 UNREACHABLE(); | 4146 UNREACHABLE(); |
4172 } | 4147 } |
4173 } | 4148 } |
4174 | 4149 |
4175 | 4150 |
4176 void Reference::SetValue(InitState init_state) { | 4151 void Reference::SetValue(InitState init_state) { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4265 } | 4240 } |
4266 break; | 4241 break; |
4267 } | 4242 } |
4268 | 4243 |
4269 case NAMED: { | 4244 case NAMED: { |
4270 Comment cmnt(masm, "[ Store to named Property"); | 4245 Comment cmnt(masm, "[ Store to named Property"); |
4271 // Call the appropriate IC code. | 4246 // Call the appropriate IC code. |
4272 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 4247 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
4273 Handle<String> name(GetName()); | 4248 Handle<String> name(GetName()); |
4274 | 4249 |
4275 Result value = cgen_->allocator()->Allocate(r0); | 4250 Result value(r0); |
4276 ASSERT(value.is_valid()); | 4251 frame->EmitPop(r0); |
4277 frame->EmitPop(value.reg()); | |
4278 | 4252 |
4279 // Setup the name register. | 4253 // Setup the name register. |
4280 Result property_name = cgen_->allocator()->Allocate(r2); | 4254 Result property_name(r2); |
4281 ASSERT(property_name.is_valid()); | 4255 __ mov(r2, Operand(name)); |
4282 __ mov(property_name.reg(), Operand(name)); | 4256 frame->CallCodeObject(ic, |
4283 Result answer = frame->CallCodeObject(ic, | 4257 RelocInfo::CODE_TARGET, |
4284 RelocInfo::CODE_TARGET, | 4258 &value, |
4285 &value, | 4259 &property_name, |
4286 &property_name, | 4260 0); |
4287 0); | 4261 frame->EmitPush(r0); |
4288 frame->EmitPush(answer.reg()); | |
4289 break; | 4262 break; |
4290 } | 4263 } |
4291 | 4264 |
4292 case KEYED: { | 4265 case KEYED: { |
4293 Comment cmnt(masm, "[ Store to keyed Property"); | 4266 Comment cmnt(masm, "[ Store to keyed Property"); |
4294 Property* property = expression_->AsProperty(); | 4267 Property* property = expression_->AsProperty(); |
4295 ASSERT(property != NULL); | 4268 ASSERT(property != NULL); |
4296 cgen_->CodeForSourcePosition(property->position()); | 4269 cgen_->CodeForSourcePosition(property->position()); |
4297 | 4270 |
4298 // Call IC code. | 4271 // Call IC code. |
4299 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 4272 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
4300 // TODO(1222589): Make the IC grab the values from the stack. | 4273 // TODO(1222589): Make the IC grab the values from the stack. |
4301 Result value = cgen_->allocator()->Allocate(r0); | 4274 Result value(r0); |
4302 ASSERT(value.is_valid()); | 4275 frame->EmitPop(r0); // value |
4303 frame->EmitPop(value.reg()); // value | 4276 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, &value, 0); |
4304 Result result = | 4277 frame->EmitPush(r0); |
4305 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, &value, 0); | |
4306 frame->EmitPush(result.reg()); | |
4307 break; | 4278 break; |
4308 } | 4279 } |
4309 | 4280 |
4310 default: | 4281 default: |
4311 UNREACHABLE(); | 4282 UNREACHABLE(); |
4312 } | 4283 } |
4313 } | 4284 } |
4314 | 4285 |
4315 | 4286 |
4316 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz | 4287 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz |
(...skipping 1945 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6262 int CompareStub::MinorKey() { | 6233 int CompareStub::MinorKey() { |
6263 // Encode the two parameters in a unique 16 bit value. | 6234 // Encode the two parameters in a unique 16 bit value. |
6264 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); | 6235 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); |
6265 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); | 6236 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); |
6266 } | 6237 } |
6267 | 6238 |
6268 | 6239 |
6269 #undef __ | 6240 #undef __ |
6270 | 6241 |
6271 } } // namespace v8::internal | 6242 } } // namespace v8::internal |
OLD | NEW |