OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 __ bind(&done); | 609 __ bind(&done); |
610 } | 610 } |
611 | 611 |
612 | 612 |
613 void FullCodeGenerator::StackValueContext::Plug( | 613 void FullCodeGenerator::StackValueContext::Plug( |
614 Label* materialize_true, | 614 Label* materialize_true, |
615 Label* materialize_false) const { | 615 Label* materialize_false) const { |
616 Label done; | 616 Label done; |
617 __ bind(materialize_true); | 617 __ bind(materialize_true); |
618 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 618 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
619 __ push(ip); | |
620 __ jmp(&done); | 619 __ jmp(&done); |
621 __ bind(materialize_false); | 620 __ bind(materialize_false); |
622 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 621 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
| 622 __ bind(&done); |
623 __ push(ip); | 623 __ push(ip); |
624 __ bind(&done); | |
625 } | 624 } |
626 | 625 |
627 | 626 |
628 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 627 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
629 Label* materialize_false) const { | 628 Label* materialize_false) const { |
630 ASSERT(materialize_true == true_label_); | 629 ASSERT(materialize_true == true_label_); |
631 ASSERT(materialize_false == false_label_); | 630 ASSERT(materialize_false == false_label_); |
632 } | 631 } |
633 | 632 |
634 | 633 |
(...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1593 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 1592 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
1594 __ mov(r5, r0); | 1593 __ mov(r5, r0); |
1595 | 1594 |
1596 __ bind(&materialized); | 1595 __ bind(&materialized); |
1597 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 1596 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
1598 Label allocated, runtime_allocate; | 1597 Label allocated, runtime_allocate; |
1599 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); | 1598 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); |
1600 __ jmp(&allocated); | 1599 __ jmp(&allocated); |
1601 | 1600 |
1602 __ bind(&runtime_allocate); | 1601 __ bind(&runtime_allocate); |
1603 __ push(r5); | |
1604 __ mov(r0, Operand(Smi::FromInt(size))); | 1602 __ mov(r0, Operand(Smi::FromInt(size))); |
1605 __ push(r0); | 1603 __ Push(r5, r0); |
1606 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 1604 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
1607 __ pop(r5); | 1605 __ pop(r5); |
1608 | 1606 |
1609 __ bind(&allocated); | 1607 __ bind(&allocated); |
1610 // After this, registers are used as follows: | 1608 // After this, registers are used as follows: |
1611 // r0: Newly allocated regexp. | 1609 // r0: Newly allocated regexp. |
1612 // r5: Materialized regexp. | 1610 // r5: Materialized regexp. |
1613 // r2: temp. | 1611 // r2: temp. |
1614 __ CopyFields(r0, r5, d0, size / kPointerSize); | 1612 __ CopyFields(r0, r5, d0, size / kPointerSize); |
1615 context()->Plug(r0); | 1613 context()->Plug(r0); |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2032 Label l_next, l_call, l_loop; | 2030 Label l_next, l_call, l_loop; |
2033 // Initial send value is undefined. | 2031 // Initial send value is undefined. |
2034 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 2032 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
2035 __ b(&l_next); | 2033 __ b(&l_next); |
2036 | 2034 |
2037 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 2035 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
2038 __ bind(&l_catch); | 2036 __ bind(&l_catch); |
2039 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 2037 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
2040 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw" | 2038 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw" |
2041 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2039 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
2042 __ push(r3); // iter | 2040 __ Push(r3, r0); // iter, exception |
2043 __ push(r0); // exception | |
2044 __ jmp(&l_call); | 2041 __ jmp(&l_call); |
2045 | 2042 |
2046 // try { received = %yield result } | 2043 // try { received = %yield result } |
2047 // Shuffle the received result above a try handler and yield it without | 2044 // Shuffle the received result above a try handler and yield it without |
2048 // re-boxing. | 2045 // re-boxing. |
2049 __ bind(&l_try); | 2046 __ bind(&l_try); |
2050 __ pop(r0); // result | 2047 __ pop(r0); // result |
2051 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2048 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
2052 const int handler_size = StackHandlerConstants::kSize; | 2049 const int handler_size = StackHandlerConstants::kSize; |
2053 __ push(r0); // result | 2050 __ push(r0); // result |
(...skipping 15 matching lines...) Expand all Loading... |
2069 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2066 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2070 __ pop(r0); // result | 2067 __ pop(r0); // result |
2071 EmitReturnSequence(); | 2068 EmitReturnSequence(); |
2072 __ bind(&l_resume); // received in r0 | 2069 __ bind(&l_resume); // received in r0 |
2073 __ PopTryHandler(); | 2070 __ PopTryHandler(); |
2074 | 2071 |
2075 // receiver = iter; f = 'next'; arg = received; | 2072 // receiver = iter; f = 'next'; arg = received; |
2076 __ bind(&l_next); | 2073 __ bind(&l_next); |
2077 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" | 2074 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" |
2078 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2075 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
2079 __ push(r3); // iter | 2076 __ Push(r3, r0); // iter, received |
2080 __ push(r0); // received | |
2081 | 2077 |
2082 // result = receiver[f](arg); | 2078 // result = receiver[f](arg); |
2083 __ bind(&l_call); | 2079 __ bind(&l_call); |
2084 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2080 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); |
2085 CallIC(ic); | 2081 CallIC(ic); |
2086 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2082 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2087 | 2083 |
2088 // if (!result.done) goto l_try; | 2084 // if (!result.done) goto l_try; |
2089 __ bind(&l_loop); | 2085 __ bind(&l_loop); |
2090 __ push(r0); // save result | 2086 __ push(r0); // save result |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2146 __ push(r2); | 2142 __ push(r2); |
2147 __ jmp(&push_argument_holes); | 2143 __ jmp(&push_argument_holes); |
2148 | 2144 |
2149 // Enter a new JavaScript frame, and initialize its slots as they were when | 2145 // Enter a new JavaScript frame, and initialize its slots as they were when |
2150 // the generator was suspended. | 2146 // the generator was suspended. |
2151 Label resume_frame; | 2147 Label resume_frame; |
2152 __ bind(&push_frame); | 2148 __ bind(&push_frame); |
2153 __ bl(&resume_frame); | 2149 __ bl(&resume_frame); |
2154 __ jmp(&done); | 2150 __ jmp(&done); |
2155 __ bind(&resume_frame); | 2151 __ bind(&resume_frame); |
2156 __ push(lr); // Return address. | 2152 // lr = return address. |
2157 __ push(fp); // Caller's frame pointer. | 2153 // fp = caller's frame pointer. |
2158 __ mov(fp, sp); | 2154 // cp = callee's context, |
2159 __ push(cp); // Callee's context. | 2155 // r4 = callee's JS function. |
2160 __ push(r4); // Callee's JS Function. | 2156 __ Push(lr, fp, cp, r4); |
| 2157 // Adjust FP to point to saved FP. |
| 2158 __ add(fp, sp, Operand(2 * kPointerSize)); |
2161 | 2159 |
2162 // Load the operand stack size. | 2160 // Load the operand stack size. |
2163 __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset)); | 2161 __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset)); |
2164 __ ldr(r3, FieldMemOperand(r3, FixedArray::kLengthOffset)); | 2162 __ ldr(r3, FieldMemOperand(r3, FixedArray::kLengthOffset)); |
2165 __ SmiUntag(r3); | 2163 __ SmiUntag(r3); |
2166 | 2164 |
2167 // If we are sending a value and there is no operand stack, we can jump back | 2165 // If we are sending a value and there is no operand stack, we can jump back |
2168 // in directly. | 2166 // in directly. |
2169 if (resume_mode == JSGeneratorObject::NEXT) { | 2167 if (resume_mode == JSGeneratorObject::NEXT) { |
2170 Label slow_resume; | 2168 Label slow_resume; |
(...skipping 11 matching lines...) Expand all Loading... |
2182 | 2180 |
2183 // Otherwise, we push holes for the operand stack and call the runtime to fix | 2181 // Otherwise, we push holes for the operand stack and call the runtime to fix |
2184 // up the stack and the handlers. | 2182 // up the stack and the handlers. |
2185 Label push_operand_holes, call_resume; | 2183 Label push_operand_holes, call_resume; |
2186 __ bind(&push_operand_holes); | 2184 __ bind(&push_operand_holes); |
2187 __ sub(r3, r3, Operand(1), SetCC); | 2185 __ sub(r3, r3, Operand(1), SetCC); |
2188 __ b(mi, &call_resume); | 2186 __ b(mi, &call_resume); |
2189 __ push(r2); | 2187 __ push(r2); |
2190 __ b(&push_operand_holes); | 2188 __ b(&push_operand_holes); |
2191 __ bind(&call_resume); | 2189 __ bind(&call_resume); |
2192 __ push(r1); | 2190 ASSERT(!result_register().is(r1)); |
2193 __ push(result_register()); | 2191 __ Push(r1, result_register()); |
2194 __ Push(Smi::FromInt(resume_mode)); | 2192 __ Push(Smi::FromInt(resume_mode)); |
2195 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2193 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
2196 // Not reached: the runtime call returns elsewhere. | 2194 // Not reached: the runtime call returns elsewhere. |
2197 __ stop("not-reached"); | 2195 __ stop("not-reached"); |
2198 | 2196 |
2199 // Throw error if we attempt to operate on a running generator. | 2197 // Throw error if we attempt to operate on a running generator. |
2200 __ bind(&wrong_state); | 2198 __ bind(&wrong_state); |
2201 __ push(r1); | 2199 __ push(r1); |
2202 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); | 2200 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
2203 | 2201 |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2405 ? isolate()->builtins()->StoreIC_Initialize() | 2403 ? isolate()->builtins()->StoreIC_Initialize() |
2406 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2404 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
2407 CallIC(ic); | 2405 CallIC(ic); |
2408 break; | 2406 break; |
2409 } | 2407 } |
2410 case KEYED_PROPERTY: { | 2408 case KEYED_PROPERTY: { |
2411 __ push(r0); // Preserve value. | 2409 __ push(r0); // Preserve value. |
2412 VisitForStackValue(prop->obj()); | 2410 VisitForStackValue(prop->obj()); |
2413 VisitForAccumulatorValue(prop->key()); | 2411 VisitForAccumulatorValue(prop->key()); |
2414 __ mov(r1, r0); | 2412 __ mov(r1, r0); |
2415 __ pop(r2); | 2413 __ Pop(r0, r2); // r0 = restored value. |
2416 __ pop(r0); // Restore value. | |
2417 Handle<Code> ic = is_classic_mode() | 2414 Handle<Code> ic = is_classic_mode() |
2418 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2415 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2419 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2416 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2420 CallIC(ic); | 2417 CallIC(ic); |
2421 break; | 2418 break; |
2422 } | 2419 } |
2423 } | 2420 } |
2424 context()->Plug(r0); | 2421 context()->Plug(r0); |
2425 } | 2422 } |
2426 | 2423 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2540 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2537 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2541 context()->Plug(r0); | 2538 context()->Plug(r0); |
2542 } | 2539 } |
2543 | 2540 |
2544 | 2541 |
2545 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2542 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2546 // Assignment to a property, using a keyed store IC. | 2543 // Assignment to a property, using a keyed store IC. |
2547 | 2544 |
2548 // Record source code position before IC call. | 2545 // Record source code position before IC call. |
2549 SetSourcePosition(expr->position()); | 2546 SetSourcePosition(expr->position()); |
2550 __ pop(r1); // Key. | 2547 __ Pop(r2, r1); // r1 = key. |
2551 __ pop(r2); | |
2552 | 2548 |
2553 Handle<Code> ic = is_classic_mode() | 2549 Handle<Code> ic = is_classic_mode() |
2554 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2550 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2555 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2551 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2556 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2552 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); |
2557 | 2553 |
2558 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2554 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2559 context()->Plug(r0); | 2555 context()->Plug(r0); |
2560 } | 2556 } |
2561 | 2557 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2670 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2666 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
2671 __ CallStub(&stub, expr->CallFeedbackId()); | 2667 __ CallStub(&stub, expr->CallFeedbackId()); |
2672 RecordJSReturnSite(expr); | 2668 RecordJSReturnSite(expr); |
2673 // Restore context register. | 2669 // Restore context register. |
2674 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2670 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2675 context()->DropAndPlug(1, r0); | 2671 context()->DropAndPlug(1, r0); |
2676 } | 2672 } |
2677 | 2673 |
2678 | 2674 |
2679 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 2675 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
2680 // Push copy of the first argument or undefined if it doesn't exist. | 2676 // r4: copy of the first argument or undefined if it doesn't exist. |
2681 if (arg_count > 0) { | 2677 if (arg_count > 0) { |
2682 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); | 2678 __ ldr(r4, MemOperand(sp, arg_count * kPointerSize)); |
2683 } else { | 2679 } else { |
2684 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); | 2680 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); |
2685 } | 2681 } |
2686 __ push(r1); | |
2687 | 2682 |
2688 // Push the receiver of the enclosing function. | 2683 // r3: the receiver of the enclosing function. |
2689 int receiver_offset = 2 + info_->scope()->num_parameters(); | 2684 int receiver_offset = 2 + info_->scope()->num_parameters(); |
2690 __ ldr(r1, MemOperand(fp, receiver_offset * kPointerSize)); | 2685 __ ldr(r3, MemOperand(fp, receiver_offset * kPointerSize)); |
2691 __ push(r1); | |
2692 // Push the language mode. | |
2693 __ mov(r1, Operand(Smi::FromInt(language_mode()))); | |
2694 __ push(r1); | |
2695 | 2686 |
2696 // Push the start position of the scope the calls resides in. | 2687 // r2: the language mode. |
| 2688 __ mov(r2, Operand(Smi::FromInt(language_mode()))); |
| 2689 |
| 2690 // r1: the start position of the scope the calls resides in. |
2697 __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); | 2691 __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); |
2698 __ push(r1); | |
2699 | 2692 |
2700 // Do the runtime call. | 2693 // Do the runtime call. |
| 2694 __ Push(r4, r3, r2, r1); |
2701 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2695 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
2702 } | 2696 } |
2703 | 2697 |
2704 | 2698 |
2705 void FullCodeGenerator::VisitCall(Call* expr) { | 2699 void FullCodeGenerator::VisitCall(Call* expr) { |
2706 #ifdef DEBUG | 2700 #ifdef DEBUG |
2707 // We want to verify that RecordJSReturnSite gets called on all paths | 2701 // We want to verify that RecordJSReturnSite gets called on all paths |
2708 // through this function. Avoid early returns. | 2702 // through this function. Avoid early returns. |
2709 expr->return_is_recorded_ = false; | 2703 expr->return_is_recorded_ = false; |
2710 #endif | 2704 #endif |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2764 | 2758 |
2765 { PreservePositionScope scope(masm()->positions_recorder()); | 2759 { PreservePositionScope scope(masm()->positions_recorder()); |
2766 // Generate code for loading from variables potentially shadowed | 2760 // Generate code for loading from variables potentially shadowed |
2767 // by eval-introduced variables. | 2761 // by eval-introduced variables. |
2768 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2762 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
2769 } | 2763 } |
2770 | 2764 |
2771 __ bind(&slow); | 2765 __ bind(&slow); |
2772 // Call the runtime to find the function to call (returned in r0) | 2766 // Call the runtime to find the function to call (returned in r0) |
2773 // and the object holding it (returned in edx). | 2767 // and the object holding it (returned in edx). |
2774 __ push(context_register()); | 2768 ASSERT(!context_register().is(r2)); |
2775 __ mov(r2, Operand(proxy->name())); | 2769 __ mov(r2, Operand(proxy->name())); |
2776 __ push(r2); | 2770 __ Push(context_register(), r2); |
2777 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 2771 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
2778 __ Push(r0, r1); // Function, receiver. | 2772 __ Push(r0, r1); // Function, receiver. |
2779 | 2773 |
2780 // If fast case code has been generated, emit code to push the | 2774 // If fast case code has been generated, emit code to push the |
2781 // function and receiver and have the slow path jump around this | 2775 // function and receiver and have the slow path jump around this |
2782 // code. | 2776 // code. |
2783 if (done.is_linked()) { | 2777 if (done.is_linked()) { |
2784 Label call; | 2778 Label call; |
2785 __ b(&call); | 2779 __ b(&call); |
2786 __ bind(&done); | 2780 __ bind(&done); |
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3483 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3477 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
3484 ZoneList<Expression*>* args = expr->arguments(); | 3478 ZoneList<Expression*>* args = expr->arguments(); |
3485 ASSERT_EQ(3, args->length()); | 3479 ASSERT_EQ(3, args->length()); |
3486 | 3480 |
3487 Register string = r0; | 3481 Register string = r0; |
3488 Register index = r1; | 3482 Register index = r1; |
3489 Register value = r2; | 3483 Register value = r2; |
3490 | 3484 |
3491 VisitForStackValue(args->at(1)); // index | 3485 VisitForStackValue(args->at(1)); // index |
3492 VisitForStackValue(args->at(2)); // value | 3486 VisitForStackValue(args->at(2)); // value |
3493 __ pop(value); | 3487 __ Pop(index, value); |
3494 __ pop(index); | |
3495 VisitForAccumulatorValue(args->at(0)); // string | 3488 VisitForAccumulatorValue(args->at(0)); // string |
3496 | 3489 |
3497 if (FLAG_debug_code) { | 3490 if (FLAG_debug_code) { |
3498 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 3491 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
3499 EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); | 3492 EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); |
3500 } | 3493 } |
3501 | 3494 |
3502 __ SmiUntag(value, value); | 3495 __ SmiUntag(value, value); |
3503 __ add(ip, | 3496 __ add(ip, |
3504 string, | 3497 string, |
3505 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3498 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3506 __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize)); | 3499 __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize)); |
3507 context()->Plug(string); | 3500 context()->Plug(string); |
3508 } | 3501 } |
3509 | 3502 |
3510 | 3503 |
3511 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { | 3504 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { |
3512 ZoneList<Expression*>* args = expr->arguments(); | 3505 ZoneList<Expression*>* args = expr->arguments(); |
3513 ASSERT_EQ(3, args->length()); | 3506 ASSERT_EQ(3, args->length()); |
3514 | 3507 |
3515 Register string = r0; | 3508 Register string = r0; |
3516 Register index = r1; | 3509 Register index = r1; |
3517 Register value = r2; | 3510 Register value = r2; |
3518 | 3511 |
3519 VisitForStackValue(args->at(1)); // index | 3512 VisitForStackValue(args->at(1)); // index |
3520 VisitForStackValue(args->at(2)); // value | 3513 VisitForStackValue(args->at(2)); // value |
3521 __ pop(value); | 3514 __ Pop(index, value); |
3522 __ pop(index); | |
3523 VisitForAccumulatorValue(args->at(0)); // string | 3515 VisitForAccumulatorValue(args->at(0)); // string |
3524 | 3516 |
3525 if (FLAG_debug_code) { | 3517 if (FLAG_debug_code) { |
3526 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 3518 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
3527 EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); | 3519 EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); |
3528 } | 3520 } |
3529 | 3521 |
3530 __ SmiUntag(value, value); | 3522 __ SmiUntag(value, value); |
3531 __ add(ip, | 3523 __ add(ip, |
3532 string, | 3524 string, |
(...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4256 __ Push(r2, r1, r0); | 4248 __ Push(r2, r1, r0); |
4257 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4249 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4258 context()->Plug(r0); | 4250 context()->Plug(r0); |
4259 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4251 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4260 // Result of deleting non-global, non-dynamic variables is false. | 4252 // Result of deleting non-global, non-dynamic variables is false. |
4261 // The subexpression does not have side effects. | 4253 // The subexpression does not have side effects. |
4262 context()->Plug(var->is_this()); | 4254 context()->Plug(var->is_this()); |
4263 } else { | 4255 } else { |
4264 // Non-global variable. Call the runtime to try to delete from the | 4256 // Non-global variable. Call the runtime to try to delete from the |
4265 // context where the variable was introduced. | 4257 // context where the variable was introduced. |
4266 __ push(context_register()); | 4258 ASSERT(!context_register().is(r2)); |
4267 __ mov(r2, Operand(var->name())); | 4259 __ mov(r2, Operand(var->name())); |
4268 __ push(r2); | 4260 __ Push(context_register(), r2); |
4269 __ CallRuntime(Runtime::kDeleteContextSlot, 2); | 4261 __ CallRuntime(Runtime::kDeleteContextSlot, 2); |
4270 context()->Plug(r0); | 4262 context()->Plug(r0); |
4271 } | 4263 } |
4272 } else { | 4264 } else { |
4273 // Result of deleting non-property, non-variable reference is true. | 4265 // Result of deleting non-property, non-variable reference is true. |
4274 // The subexpression may have side effects. | 4266 // The subexpression may have side effects. |
4275 VisitForEffect(expr->expression()); | 4267 VisitForEffect(expr->expression()); |
4276 context()->Plug(true); | 4268 context()->Plug(true); |
4277 } | 4269 } |
4278 break; | 4270 break; |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4488 if (expr->is_postfix()) { | 4480 if (expr->is_postfix()) { |
4489 if (!context()->IsEffect()) { | 4481 if (!context()->IsEffect()) { |
4490 context()->PlugTOS(); | 4482 context()->PlugTOS(); |
4491 } | 4483 } |
4492 } else { | 4484 } else { |
4493 context()->Plug(r0); | 4485 context()->Plug(r0); |
4494 } | 4486 } |
4495 break; | 4487 break; |
4496 } | 4488 } |
4497 case KEYED_PROPERTY: { | 4489 case KEYED_PROPERTY: { |
4498 __ pop(r1); // Key. | 4490 __ Pop(r2, r1); // r1 = key. r2 = receiver. |
4499 __ pop(r2); // Receiver. | |
4500 Handle<Code> ic = is_classic_mode() | 4491 Handle<Code> ic = is_classic_mode() |
4501 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4492 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
4502 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4493 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
4503 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | 4494 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); |
4504 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4495 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4505 if (expr->is_postfix()) { | 4496 if (expr->is_postfix()) { |
4506 if (!context()->IsEffect()) { | 4497 if (!context()->IsEffect()) { |
4507 context()->PlugTOS(); | 4498 context()->PlugTOS(); |
4508 } | 4499 } |
4509 } else { | 4500 } else { |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4962 ASSERT(Memory::uint32_at(interrupt_address_pointer) == | 4953 ASSERT(Memory::uint32_at(interrupt_address_pointer) == |
4963 reinterpret_cast<uint32_t>( | 4954 reinterpret_cast<uint32_t>( |
4964 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4955 isolate->builtins()->OsrAfterStackCheck()->entry())); |
4965 return OSR_AFTER_STACK_CHECK; | 4956 return OSR_AFTER_STACK_CHECK; |
4966 } | 4957 } |
4967 | 4958 |
4968 | 4959 |
4969 } } // namespace v8::internal | 4960 } } // namespace v8::internal |
4970 | 4961 |
4971 #endif // V8_TARGET_ARCH_ARM | 4962 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |