| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 196 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 197 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 197 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
| 198 (num_parameters - 1 - i) * kPointerSize; | 198 (num_parameters - 1 - i) * kPointerSize; |
| 199 // Load parameter from stack. | 199 // Load parameter from stack. |
| 200 __ ldr(r0, MemOperand(fp, parameter_offset)); | 200 __ ldr(r0, MemOperand(fp, parameter_offset)); |
| 201 // Store it in the context. | 201 // Store it in the context. |
| 202 MemOperand target = ContextOperand(cp, slot->index()); | 202 MemOperand target = ContextOperand(cp, slot->index()); |
| 203 __ str(r0, target); | 203 __ str(r0, target); |
| 204 | 204 |
| 205 // Update the write barrier. | 205 // Update the write barrier. |
| 206 __ RecordWriteContextSlot(cp, target.offset(), r0, r3, kDontSaveFPRegs); | 206 __ RecordWriteContextSlot( |
| 207 cp, target.offset(), r0, r3, kLRHasBeenSaved, kDontSaveFPRegs); |
| 207 } | 208 } |
| 208 } | 209 } |
| 209 } | 210 } |
| 210 | 211 |
| 211 Variable* arguments = scope()->arguments(); | 212 Variable* arguments = scope()->arguments(); |
| 212 if (arguments != NULL) { | 213 if (arguments != NULL) { |
| 213 // Function uses arguments object. | 214 // Function uses arguments object. |
| 214 Comment cmnt(masm_, "[ Allocate arguments object"); | 215 Comment cmnt(masm_, "[ Allocate arguments object"); |
| 215 if (!function_in_register) { | 216 if (!function_in_register) { |
| 216 // Load this again, if it's used by the local context below. | 217 // Load this again, if it's used by the local context below. |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 Register src, | 642 Register src, |
| 642 Register scratch1, | 643 Register scratch1, |
| 643 Register scratch2) { | 644 Register scratch2) { |
| 644 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 645 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
| 645 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 646 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
| 646 MemOperand location = EmitSlotSearch(dst, scratch1); | 647 MemOperand location = EmitSlotSearch(dst, scratch1); |
| 647 __ str(src, location); | 648 __ str(src, location); |
| 648 | 649 |
| 649 // Emit the write barrier code if the location is in the heap. | 650 // Emit the write barrier code if the location is in the heap. |
| 650 if (dst->type() == Slot::CONTEXT) { | 651 if (dst->type() == Slot::CONTEXT) { |
| 651 __ RecordWriteContextSlot( | 652 __ RecordWriteContextSlot(scratch1, |
| 652 scratch1, location.offset(), src, scratch2, kDontSaveFPRegs); | 653 location.offset(), |
| 654 src, |
| 655 scratch2, |
| 656 kLRHasBeenSaved, |
| 657 kDontSaveFPRegs); |
| 653 } | 658 } |
| 654 } | 659 } |
| 655 | 660 |
| 656 | 661 |
| 657 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, | 662 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, |
| 658 bool should_normalize, | 663 bool should_normalize, |
| 659 Label* if_true, | 664 Label* if_true, |
| 660 Label* if_false) { | 665 Label* if_false) { |
| 661 // Only prepare for bailouts before splits if we're in a test | 666 // Only prepare for bailouts before splits if we're in a test |
| 662 // context. Otherwise, we let the Visit function deal with the | 667 // context. Otherwise, we let the Visit function deal with the |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 } else if (function != NULL) { | 727 } else if (function != NULL) { |
| 723 VisitForAccumulatorValue(function); | 728 VisitForAccumulatorValue(function); |
| 724 MemOperand target = ContextOperand(cp, slot->index()); | 729 MemOperand target = ContextOperand(cp, slot->index()); |
| 725 __ str(result_register(), target); | 730 __ str(result_register(), target); |
| 726 | 731 |
| 727 // We know that we have written a function, which is not a smi. | 732 // We know that we have written a function, which is not a smi. |
| 728 __ RecordWriteContextSlot(cp, | 733 __ RecordWriteContextSlot(cp, |
| 729 target.offset(), | 734 target.offset(), |
| 730 result_register(), | 735 result_register(), |
| 731 r2, | 736 r2, |
| 737 kLRHasBeenSaved, |
| 732 kDontSaveFPRegs, | 738 kDontSaveFPRegs, |
| 733 EMIT_REMEMBERED_SET, | 739 EMIT_REMEMBERED_SET, |
| 734 OMIT_SMI_CHECK); | 740 OMIT_SMI_CHECK); |
| 735 } | 741 } |
| 736 break; | 742 break; |
| 737 | 743 |
| 738 case Slot::LOOKUP: { | 744 case Slot::LOOKUP: { |
| 739 __ mov(r2, Operand(variable->name())); | 745 __ mov(r2, Operand(variable->name())); |
| 740 // Declaration nodes are always introduced in one of two modes. | 746 // Declaration nodes are always introduced in one of two modes. |
| 741 ASSERT(mode == Variable::VAR || | 747 ASSERT(mode == Variable::VAR || |
| (...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1546 VisitForAccumulatorValue(subexpr); | 1552 VisitForAccumulatorValue(subexpr); |
| 1547 | 1553 |
| 1548 // Store the subexpression value in the array's elements. | 1554 // Store the subexpression value in the array's elements. |
| 1549 __ ldr(r1, MemOperand(sp)); // Copy of array literal. | 1555 __ ldr(r1, MemOperand(sp)); // Copy of array literal. |
| 1550 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); | 1556 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); |
| 1551 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 1557 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
| 1552 __ str(result_register(), FieldMemOperand(r1, offset)); | 1558 __ str(result_register(), FieldMemOperand(r1, offset)); |
| 1553 | 1559 |
| 1554 // Update the write barrier for the array store with r0 as the scratch | 1560 // Update the write barrier for the array store with r0 as the scratch |
| 1555 // register. | 1561 // register. |
| 1556 __ RecordWriteField(r1, offset, result_register(), r2, kDontSaveFPRegs); | 1562 __ RecordWriteField( |
| 1563 r1, offset, result_register(), r2, kLRHasBeenSaved, kDontSaveFPRegs); |
| 1557 | 1564 |
| 1558 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); | 1565 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); |
| 1559 } | 1566 } |
| 1560 | 1567 |
| 1561 if (result_saved) { | 1568 if (result_saved) { |
| 1562 context()->PlugTOS(); | 1569 context()->PlugTOS(); |
| 1563 } else { | 1570 } else { |
| 1564 context()->Plug(r0); | 1571 context()->Plug(r0); |
| 1565 } | 1572 } |
| 1566 } | 1573 } |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1928 break; | 1935 break; |
| 1929 case Slot::CONTEXT: { | 1936 case Slot::CONTEXT: { |
| 1930 __ ldr(r1, ContextOperand(cp, Context::FCONTEXT_INDEX)); | 1937 __ ldr(r1, ContextOperand(cp, Context::FCONTEXT_INDEX)); |
| 1931 __ ldr(r2, ContextOperand(r1, slot->index())); | 1938 __ ldr(r2, ContextOperand(r1, slot->index())); |
| 1932 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 1939 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 1933 __ cmp(r2, ip); | 1940 __ cmp(r2, ip); |
| 1934 __ b(ne, &skip); | 1941 __ b(ne, &skip); |
| 1935 MemOperand target = ContextOperand(r1, slot->index()); | 1942 MemOperand target = ContextOperand(r1, slot->index()); |
| 1936 __ str(r0, target); | 1943 __ str(r0, target); |
| 1937 __ mov(r3, r0); // Preserve the stored value in r0. | 1944 __ mov(r3, r0); // Preserve the stored value in r0. |
| 1938 __ RecordWriteContextSlot(r1, target.offset(), r3, r2, kDontSaveFPRegs); | 1945 __ RecordWriteContextSlot( |
| 1946 r1, target.offset(), r3, r2, kLRHasBeenSaved, kDontSaveFPRegs); |
| 1939 break; | 1947 break; |
| 1940 } | 1948 } |
| 1941 case Slot::LOOKUP: | 1949 case Slot::LOOKUP: |
| 1942 __ push(r0); | 1950 __ push(r0); |
| 1943 __ mov(r0, Operand(slot->var()->name())); | 1951 __ mov(r0, Operand(slot->var()->name())); |
| 1944 __ Push(cp, r0); // Context and name. | 1952 __ Push(cp, r0); // Context and name. |
| 1945 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1953 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 1946 break; | 1954 break; |
| 1947 } | 1955 } |
| 1948 __ bind(&skip); | 1956 __ bind(&skip); |
| 1949 | 1957 |
| 1950 } else if (var->mode() != Variable::CONST) { | 1958 } else if (var->mode() != Variable::CONST) { |
| 1951 // Perform the assignment for non-const variables. Const assignments | 1959 // Perform the assignment for non-const variables. Const assignments |
| 1952 // are simply skipped. | 1960 // are simply skipped. |
| 1953 Slot* slot = var->AsSlot(); | 1961 Slot* slot = var->AsSlot(); |
| 1954 switch (slot->type()) { | 1962 switch (slot->type()) { |
| 1955 case Slot::PARAMETER: | 1963 case Slot::PARAMETER: |
| 1956 case Slot::LOCAL: | 1964 case Slot::LOCAL: |
| 1957 // Perform the assignment. | 1965 // Perform the assignment. |
| 1958 __ str(result_register(), MemOperand(fp, SlotOffset(slot))); | 1966 __ str(result_register(), MemOperand(fp, SlotOffset(slot))); |
| 1959 break; | 1967 break; |
| 1960 | 1968 |
| 1961 case Slot::CONTEXT: { | 1969 case Slot::CONTEXT: { |
| 1962 MemOperand target = EmitSlotSearch(slot, r1); | 1970 MemOperand target = EmitSlotSearch(slot, r1); |
| 1963 // Perform the assignment and issue the write barrier. | 1971 // Perform the assignment and issue the write barrier. |
| 1964 __ str(result_register(), target); | 1972 __ str(result_register(), target); |
| 1965 // The value of the assignment is in result_register(). RecordWrite | 1973 // The value of the assignment is in result_register(). RecordWrite |
| 1966 // clobbers its second and third register arguments. | 1974 // clobbers its second and third register arguments. |
| 1967 __ mov(r3, result_register()); | 1975 __ mov(r3, result_register()); |
| 1968 __ RecordWriteContextSlot(r1, target.offset(), r3, r2, kDontSaveFPRegs); | 1976 __ RecordWriteContextSlot( |
| 1977 r1, target.offset(), r3, r2, kLRHasBeenSaved, kDontSaveFPRegs); |
| 1969 break; | 1978 break; |
| 1970 } | 1979 } |
| 1971 | 1980 |
| 1972 case Slot::LOOKUP: | 1981 case Slot::LOOKUP: |
| 1973 // Call the runtime for the assignment. | 1982 // Call the runtime for the assignment. |
| 1974 __ push(r0); // Value. | 1983 __ push(r0); // Value. |
| 1975 __ mov(r1, Operand(slot->var()->name())); | 1984 __ mov(r1, Operand(slot->var()->name())); |
| 1976 __ mov(r0, Operand(Smi::FromInt(strict_mode_flag()))); | 1985 __ mov(r0, Operand(Smi::FromInt(strict_mode_flag()))); |
| 1977 __ Push(cp, r1, r0); // Context, name, strict mode. | 1986 __ Push(cp, r1, r0); // Context, name, strict mode. |
| 1978 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 1987 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
| (...skipping 983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2962 | 2971 |
| 2963 // If the object is not a value type, return the value. | 2972 // If the object is not a value type, return the value. |
| 2964 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); | 2973 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); |
| 2965 __ b(ne, &done); | 2974 __ b(ne, &done); |
| 2966 | 2975 |
| 2967 // Store the value. | 2976 // Store the value. |
| 2968 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); | 2977 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); |
| 2969 // Update the write barrier. Save the value as it will be | 2978 // Update the write barrier. Save the value as it will be |
| 2970 // overwritten by the write barrier code and is needed afterward. | 2979 // overwritten by the write barrier code and is needed afterward. |
| 2971 __ mov(r2, r0); | 2980 __ mov(r2, r0); |
| 2972 __ RecordWriteField(r1, JSValue::kValueOffset, r2, r3, kDontSaveFPRegs); | 2981 __ RecordWriteField( |
| 2982 r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); |
| 2973 | 2983 |
| 2974 __ bind(&done); | 2984 __ bind(&done); |
| 2975 context()->Plug(r0); | 2985 context()->Plug(r0); |
| 2976 } | 2986 } |
| 2977 | 2987 |
| 2978 | 2988 |
| 2979 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { | 2989 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { |
| 2980 ASSERT_EQ(args->length(), 1); | 2990 ASSERT_EQ(args->length(), 1); |
| 2981 | 2991 |
| 2982 // Load the argument on the stack and call the stub. | 2992 // Load the argument on the stack and call the stub. |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3258 | 3268 |
| 3259 Label no_remembered_set; | 3269 Label no_remembered_set; |
| 3260 __ CheckPageFlag(elements, | 3270 __ CheckPageFlag(elements, |
| 3261 scratch1, | 3271 scratch1, |
| 3262 MemoryChunk::SCAN_ON_SCAVENGE, | 3272 MemoryChunk::SCAN_ON_SCAVENGE, |
| 3263 ne, | 3273 ne, |
| 3264 &no_remembered_set); | 3274 &no_remembered_set); |
| 3265 // Possible optimization: do a check that both values are Smis | 3275 // Possible optimization: do a check that both values are Smis |
| 3266 // (or them and test against Smi mask.) | 3276 // (or them and test against Smi mask.) |
| 3267 | 3277 |
| 3268 __ RememberedSetHelper(index1, scratch2, kDontSaveFPRegs); | 3278 __ RememberedSetHelper( |
| 3269 __ RememberedSetHelper(index2, scratch2, kDontSaveFPRegs); | 3279 index1, scratch2, kDontSaveFPRegs, MacroAssembler::kFallThroughAtEnd); |
| 3280 __ RememberedSetHelper( |
| 3281 index2, scratch2, kDontSaveFPRegs, MacroAssembler::kFallThroughAtEnd); |
| 3270 | 3282 |
| 3271 __ bind(&no_remembered_set); | 3283 __ bind(&no_remembered_set); |
| 3272 // We are done. Drop elements from the stack, and return undefined. | 3284 // We are done. Drop elements from the stack, and return undefined. |
| 3273 __ Drop(3); | 3285 __ Drop(3); |
| 3274 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 3286 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 3275 __ jmp(&done); | 3287 __ jmp(&done); |
| 3276 | 3288 |
| 3277 __ bind(&slow_case); | 3289 __ bind(&slow_case); |
| 3278 __ CallRuntime(Runtime::kSwapElements, 3); | 3290 __ CallRuntime(Runtime::kSwapElements, 3); |
| 3279 | 3291 |
| (...skipping 1094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4374 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 4386 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 4375 __ add(pc, r1, Operand(masm_->CodeObject())); | 4387 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 4376 } | 4388 } |
| 4377 | 4389 |
| 4378 | 4390 |
| 4379 #undef __ | 4391 #undef __ |
| 4380 | 4392 |
| 4381 } } // namespace v8::internal | 4393 } } // namespace v8::internal |
| 4382 | 4394 |
| 4383 #endif // V8_TARGET_ARCH_ARM | 4395 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |