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