| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 for (int i = 0; i < num_parameters; i++) { | 163 for (int i = 0; i < num_parameters; i++) { |
| 164 Slot* slot = scope()->parameter(i)->AsSlot(); | 164 Slot* slot = scope()->parameter(i)->AsSlot(); |
| 165 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 165 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 166 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 166 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
| 167 (num_parameters - 1 - i) * kPointerSize; | 167 (num_parameters - 1 - i) * kPointerSize; |
| 168 // Load parameter from stack. | 168 // Load parameter from stack. |
| 169 __ mov(eax, Operand(ebp, parameter_offset)); | 169 __ mov(eax, Operand(ebp, parameter_offset)); |
| 170 // Store it in the context. | 170 // Store it in the context. |
| 171 int context_offset = Context::SlotOffset(slot->index()); | 171 int context_offset = Context::SlotOffset(slot->index()); |
| 172 __ mov(Operand(esi, context_offset), eax); | 172 __ mov(Operand(esi, context_offset), eax); |
| 173 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | |
| 174 // Update the write barrier. This clobbers all involved | 173 // Update the write barrier. This clobbers all involved |
| 175 // registers, so we have use a third register to avoid | 174 // registers, so we have use a third register to avoid |
| 176 // clobbering esi. | 175 // clobbering esi. |
| 177 __ mov(ecx, esi); | 176 __ mov(ecx, esi); |
| 178 __ RecordWrite(ecx, context_offset, eax, ebx); | 177 __ RecordWrite(ecx, context_offset, eax, ebx, kDontSaveFPRegs); |
| 179 #endif | |
| 180 } | 178 } |
| 181 } | 179 } |
| 182 } | 180 } |
| 183 | 181 |
| 184 Variable* arguments = scope()->arguments(); | 182 Variable* arguments = scope()->arguments(); |
| 185 if (arguments != NULL) { | 183 if (arguments != NULL) { |
| 186 // Function uses arguments object. | 184 // Function uses arguments object. |
| 187 Comment cmnt(masm_, "[ Allocate arguments object"); | 185 Comment cmnt(masm_, "[ Allocate arguments object"); |
| 188 if (function_in_register) { | 186 if (function_in_register) { |
| 189 __ push(edi); | 187 __ push(edi); |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 | 594 |
| 597 void FullCodeGenerator::Move(Slot* dst, | 595 void FullCodeGenerator::Move(Slot* dst, |
| 598 Register src, | 596 Register src, |
| 599 Register scratch1, | 597 Register scratch1, |
| 600 Register scratch2) { | 598 Register scratch2) { |
| 601 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 599 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
| 602 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 600 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
| 603 MemOperand location = EmitSlotSearch(dst, scratch1); | 601 MemOperand location = EmitSlotSearch(dst, scratch1); |
| 604 __ mov(location, src); | 602 __ mov(location, src); |
| 605 | 603 |
| 606 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | |
| 607 // Emit the write barrier code if the location is in the heap. | 604 // Emit the write barrier code if the location is in the heap. |
| 608 if (dst->type() == Slot::CONTEXT) { | 605 if (dst->type() == Slot::CONTEXT) { |
| 609 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; | 606 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
| 610 __ RecordWrite(scratch1, offset, src, scratch2); | 607 __ RecordWrite(scratch1, offset, src, scratch2, kDontSaveFPRegs); |
| 611 } | 608 } |
| 612 #endif | |
| 613 } | 609 } |
| 614 | 610 |
| 615 | 611 |
| 616 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, | 612 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, |
| 617 bool should_normalize, | 613 bool should_normalize, |
| 618 Label* if_true, | 614 Label* if_true, |
| 619 Label* if_false) { | 615 Label* if_false) { |
| 620 // Only prepare for bailouts before splits if we're in a test | 616 // Only prepare for bailouts before splits if we're in a test |
| 621 // context. Otherwise, we let the Visit function deal with the | 617 // context. Otherwise, we let the Visit function deal with the |
| 622 // preparation to avoid preparing with the same AST id twice. | 618 // preparation to avoid preparing with the same AST id twice. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 __ cmp(ebx, Operand(esi)); | 667 __ cmp(ebx, Operand(esi)); |
| 672 __ Check(equal, "Unexpected declaration in current context."); | 668 __ Check(equal, "Unexpected declaration in current context."); |
| 673 } | 669 } |
| 674 if (mode == Variable::CONST) { | 670 if (mode == Variable::CONST) { |
| 675 __ mov(ContextOperand(esi, slot->index()), | 671 __ mov(ContextOperand(esi, slot->index()), |
| 676 Immediate(Factory::the_hole_value())); | 672 Immediate(Factory::the_hole_value())); |
| 677 // No write barrier since the hole value is in old space. | 673 // No write barrier since the hole value is in old space. |
| 678 } else if (function != NULL) { | 674 } else if (function != NULL) { |
| 679 VisitForAccumulatorValue(function); | 675 VisitForAccumulatorValue(function); |
| 680 __ mov(ContextOperand(esi, slot->index()), result_register()); | 676 __ mov(ContextOperand(esi, slot->index()), result_register()); |
| 681 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | |
| 682 int offset = Context::SlotOffset(slot->index()); | 677 int offset = Context::SlotOffset(slot->index()); |
| 683 __ mov(ebx, esi); | 678 __ mov(ebx, esi); |
| 684 __ RecordWrite(ebx, offset, result_register(), ecx); | 679 __ RecordWrite(ebx, offset, result_register(), ecx, kDontSaveFPRegs); |
| 685 #endif | |
| 686 } | 680 } |
| 687 break; | 681 break; |
| 688 | 682 |
| 689 case Slot::LOOKUP: { | 683 case Slot::LOOKUP: { |
| 690 __ push(esi); | 684 __ push(esi); |
| 691 __ push(Immediate(variable->name())); | 685 __ push(Immediate(variable->name())); |
| 692 // Declaration nodes are always introduced in one of two modes. | 686 // Declaration nodes are always introduced in one of two modes. |
| 693 ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 687 ASSERT(mode == Variable::VAR || mode == Variable::CONST); |
| 694 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; | 688 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; |
| 695 __ push(Immediate(Smi::FromInt(attr))); | 689 __ push(Immediate(Smi::FromInt(attr))); |
| (...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1445 result_saved = true; | 1439 result_saved = true; |
| 1446 } | 1440 } |
| 1447 VisitForAccumulatorValue(subexpr); | 1441 VisitForAccumulatorValue(subexpr); |
| 1448 | 1442 |
| 1449 // Store the subexpression value in the array's elements. | 1443 // Store the subexpression value in the array's elements. |
| 1450 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. | 1444 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. |
| 1451 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); | 1445 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); |
| 1452 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 1446 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
| 1453 __ mov(FieldOperand(ebx, offset), result_register()); | 1447 __ mov(FieldOperand(ebx, offset), result_register()); |
| 1454 | 1448 |
| 1455 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | |
| 1456 // Update the write barrier for the array store. | 1449 // Update the write barrier for the array store. |
| 1457 __ RecordWrite(ebx, offset, result_register(), ecx); | 1450 __ RecordWrite(ebx, offset, result_register(), ecx, kDontSaveFPRegs); |
| 1458 #endif | |
| 1459 | 1451 |
| 1460 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); | 1452 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); |
| 1461 } | 1453 } |
| 1462 | 1454 |
| 1463 if (result_saved) { | 1455 if (result_saved) { |
| 1464 context()->PlugTOS(); | 1456 context()->PlugTOS(); |
| 1465 } else { | 1457 } else { |
| 1466 context()->Plug(eax); | 1458 context()->Plug(eax); |
| 1467 } | 1459 } |
| 1468 } | 1460 } |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2017 MemOperand target = EmitSlotSearch(slot, ecx); | 2009 MemOperand target = EmitSlotSearch(slot, ecx); |
| 2018 if (op == Token::INIT_CONST) { | 2010 if (op == Token::INIT_CONST) { |
| 2019 // Detect const reinitialization by checking for the hole value. | 2011 // Detect const reinitialization by checking for the hole value. |
| 2020 __ mov(edx, target); | 2012 __ mov(edx, target); |
| 2021 __ cmp(edx, Factory::the_hole_value()); | 2013 __ cmp(edx, Factory::the_hole_value()); |
| 2022 __ j(not_equal, &done); | 2014 __ j(not_equal, &done); |
| 2023 } | 2015 } |
| 2024 // Perform the assignment and issue the write barrier. | 2016 // Perform the assignment and issue the write barrier. |
| 2025 __ mov(target, eax); | 2017 __ mov(target, eax); |
| 2026 | 2018 |
| 2027 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | |
| 2028 // The value of the assignment is in eax. RecordWrite clobbers its | 2019 // The value of the assignment is in eax. RecordWrite clobbers its |
| 2029 // register arguments. | 2020 // register arguments. |
| 2030 __ mov(edx, eax); | 2021 __ mov(edx, eax); |
| 2031 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 2022 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 2032 __ RecordWrite(ecx, offset, edx, ebx); | 2023 __ RecordWrite(ecx, offset, edx, ebx, kDontSaveFPRegs); |
| 2033 #endif | |
| 2034 break; | 2024 break; |
| 2035 } | 2025 } |
| 2036 | 2026 |
| 2037 case Slot::LOOKUP: | 2027 case Slot::LOOKUP: |
| 2038 // Call the runtime for the assignment. The runtime will ignore | 2028 // Call the runtime for the assignment. The runtime will ignore |
| 2039 // const reinitialization. | 2029 // const reinitialization. |
| 2040 __ push(eax); // Value. | 2030 __ push(eax); // Value. |
| 2041 __ push(esi); // Context. | 2031 __ push(esi); // Context. |
| 2042 __ push(Immediate(var->name())); | 2032 __ push(Immediate(var->name())); |
| 2043 if (op == Token::INIT_CONST) { | 2033 if (op == Token::INIT_CONST) { |
| (...skipping 855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2899 } | 2889 } |
| 2900 | 2890 |
| 2901 | 2891 |
| 2902 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { | 2892 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { |
| 2903 ASSERT(args->length() == 2); | 2893 ASSERT(args->length() == 2); |
| 2904 | 2894 |
| 2905 VisitForStackValue(args->at(0)); // Load the object. | 2895 VisitForStackValue(args->at(0)); // Load the object. |
| 2906 VisitForAccumulatorValue(args->at(1)); // Load the value. | 2896 VisitForAccumulatorValue(args->at(1)); // Load the value. |
| 2907 __ pop(ebx); // eax = value. ebx = object. | 2897 __ pop(ebx); // eax = value. ebx = object. |
| 2908 | 2898 |
| 2909 NearLabel done; | 2899 Label done; |
| 2910 // If the object is a smi, return the value. | 2900 // If the object is a smi, return the value. |
| 2911 __ test(ebx, Immediate(kSmiTagMask)); | 2901 __ test(ebx, Immediate(kSmiTagMask)); |
| 2912 __ j(zero, &done); | 2902 __ j(zero, &done); |
| 2913 | 2903 |
| 2914 // If the object is not a value type, return the value. | 2904 // If the object is not a value type, return the value. |
| 2915 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); | 2905 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); |
| 2916 __ j(not_equal, &done); | 2906 __ j(not_equal, &done); |
| 2917 | 2907 |
| 2918 // Store the value. | 2908 // Store the value. |
| 2919 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); | 2909 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); |
| 2920 | 2910 |
| 2921 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | |
| 2922 // Update the write barrier. Save the value as it will be | 2911 // Update the write barrier. Save the value as it will be |
| 2923 // overwritten by the write barrier code and is needed afterward. | 2912 // overwritten by the write barrier code and is needed afterward. |
| 2924 __ mov(edx, eax); | 2913 __ mov(edx, eax); |
| 2925 __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx); | 2914 __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs); |
| 2926 #endif | |
| 2927 | 2915 |
| 2928 __ bind(&done); | 2916 __ bind(&done); |
| 2929 context()->Plug(eax); | 2917 context()->Plug(eax); |
| 2930 } | 2918 } |
| 2931 | 2919 |
| 2932 | 2920 |
| 2933 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { | 2921 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { |
| 2934 ASSERT_EQ(args->length(), 1); | 2922 ASSERT_EQ(args->length(), 1); |
| 2935 | 2923 |
| 2936 // Load the argument on the stack and call the stub. | 2924 // Load the argument on the stack and call the stub. |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3199 // Bring addresses into index1 and index2. | 3187 // Bring addresses into index1 and index2. |
| 3200 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1)); | 3188 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1)); |
| 3201 __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2)); | 3189 __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2)); |
| 3202 | 3190 |
| 3203 // Swap elements. Use object and temp as scratch registers. | 3191 // Swap elements. Use object and temp as scratch registers. |
| 3204 __ mov(object, Operand(index_1, 0)); | 3192 __ mov(object, Operand(index_1, 0)); |
| 3205 __ mov(temp, Operand(index_2, 0)); | 3193 __ mov(temp, Operand(index_2, 0)); |
| 3206 __ mov(Operand(index_2, 0), object); | 3194 __ mov(Operand(index_2, 0), object); |
| 3207 __ mov(Operand(index_1, 0), temp); | 3195 __ mov(Operand(index_1, 0), temp); |
| 3208 | 3196 |
| 3209 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | |
| 3210 Label new_space; | 3197 Label new_space; |
| 3211 __ InNewSpace(elements, temp, equal, &new_space); | 3198 __ InNewSpace(elements, temp, equal, &new_space); |
| 3212 | 3199 |
| 3213 __ mov(object, elements); | 3200 __ mov(object, elements); |
| 3214 __ RecordWriteHelper(object, index_1, temp); | 3201 __ RecordWriteHelper(object, index_1, temp, kDontSaveFPRegs); |
| 3215 __ RecordWriteHelper(elements, index_2, temp); | 3202 __ RecordWriteHelper(elements, index_2, temp, kDontSaveFPRegs); |
| 3216 | 3203 |
| 3217 __ bind(&new_space); | 3204 __ bind(&new_space); |
| 3218 #endif | |
| 3219 | 3205 |
| 3220 // We are done. Drop elements from the stack, and return undefined. | 3206 // We are done. Drop elements from the stack, and return undefined. |
| 3221 __ add(Operand(esp), Immediate(3 * kPointerSize)); | 3207 __ add(Operand(esp), Immediate(3 * kPointerSize)); |
| 3222 __ mov(eax, Factory::undefined_value()); | 3208 __ mov(eax, Factory::undefined_value()); |
| 3223 __ jmp(&done); | 3209 __ jmp(&done); |
| 3224 | 3210 |
| 3225 __ bind(&slow_case); | 3211 __ bind(&slow_case); |
| 3226 __ CallRuntime(Runtime::kSwapElements, 3); | 3212 __ CallRuntime(Runtime::kSwapElements, 3); |
| 3227 | 3213 |
| 3228 __ bind(&done); | 3214 __ bind(&done); |
| (...skipping 1049 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4278 // And return. | 4264 // And return. |
| 4279 __ ret(0); | 4265 __ ret(0); |
| 4280 } | 4266 } |
| 4281 | 4267 |
| 4282 | 4268 |
| 4283 #undef __ | 4269 #undef __ |
| 4284 | 4270 |
| 4285 } } // namespace v8::internal | 4271 } } // namespace v8::internal |
| 4286 | 4272 |
| 4287 #endif // V8_TARGET_ARCH_IA32 | 4273 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |