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 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 for (int i = 0; i < num_parameters; i++) { | 205 for (int i = 0; i < num_parameters; i++) { |
206 Variable* var = scope()->parameter(i); | 206 Variable* var = scope()->parameter(i); |
207 if (var->IsContextSlot()) { | 207 if (var->IsContextSlot()) { |
208 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 208 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
209 (num_parameters - 1 - i) * kPointerSize; | 209 (num_parameters - 1 - i) * kPointerSize; |
210 // Load parameter from stack. | 210 // Load parameter from stack. |
211 __ mov(eax, Operand(ebp, parameter_offset)); | 211 __ mov(eax, Operand(ebp, parameter_offset)); |
212 // Store it in the context. | 212 // Store it in the context. |
213 int context_offset = Context::SlotOffset(var->index()); | 213 int context_offset = Context::SlotOffset(var->index()); |
214 __ mov(Operand(esi, context_offset), eax); | 214 __ mov(Operand(esi, context_offset), eax); |
215 // Update the write barrier. This clobbers all involved | 215 // Update the write barrier. This clobbers eax and ebx. |
216 // registers, so we have to use a third register to avoid | 216 __ RecordWriteContextSlot(esi, |
217 // clobbering esi. | 217 context_offset, |
218 __ mov(ecx, esi); | 218 eax, |
219 __ RecordWrite(ecx, context_offset, eax, ebx); | 219 ebx, |
| 220 kDontSaveFPRegs); |
220 } | 221 } |
221 } | 222 } |
222 Comment(";;; End allocate local context"); | 223 Comment(";;; End allocate local context"); |
223 } | 224 } |
224 | 225 |
225 // Trace the call. | 226 // Trace the call. |
226 if (FLAG_trace) { | 227 if (FLAG_trace) { |
227 // We have not executed any compiled code yet, so esi still holds the | 228 // We have not executed any compiled code yet, so esi still holds the |
228 // incoming context. | 229 // incoming context. |
229 __ CallRuntime(Runtime::kTraceEnter, 0); | 230 __ CallRuntime(Runtime::kTraceEnter, 0); |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 inlined_function_count_ = deoptimization_literals_.length(); | 671 inlined_function_count_ = deoptimization_literals_.length(); |
671 } | 672 } |
672 | 673 |
673 | 674 |
674 void LCodeGen::RecordSafepoint( | 675 void LCodeGen::RecordSafepoint( |
675 LPointerMap* pointers, | 676 LPointerMap* pointers, |
676 Safepoint::Kind kind, | 677 Safepoint::Kind kind, |
677 int arguments, | 678 int arguments, |
678 int deoptimization_index) { | 679 int deoptimization_index) { |
679 ASSERT(kind == expected_safepoint_kind_); | 680 ASSERT(kind == expected_safepoint_kind_); |
680 const ZoneList<LOperand*>* operands = pointers->operands(); | 681 const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); |
681 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 682 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
682 kind, arguments, deoptimization_index); | 683 kind, arguments, deoptimization_index); |
683 for (int i = 0; i < operands->length(); i++) { | 684 for (int i = 0; i < operands->length(); i++) { |
684 LOperand* pointer = operands->at(i); | 685 LOperand* pointer = operands->at(i); |
685 if (pointer->IsStackSlot()) { | 686 if (pointer->IsStackSlot()) { |
686 safepoint.DefinePointerSlot(pointer->index()); | 687 safepoint.DefinePointerSlot(pointer->index()); |
687 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 688 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
688 safepoint.DefinePointerRegister(ToRegister(pointer)); | 689 safepoint.DefinePointerRegister(ToRegister(pointer)); |
689 } | 690 } |
690 } | 691 } |
(...skipping 1339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2030 | 2031 |
2031 __ mov(ecx, instr->name()); | 2032 __ mov(ecx, instr->name()); |
2032 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : | 2033 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : |
2033 RelocInfo::CODE_TARGET_CONTEXT; | 2034 RelocInfo::CODE_TARGET_CONTEXT; |
2034 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2035 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2035 CallCode(ic, mode, instr); | 2036 CallCode(ic, mode, instr); |
2036 } | 2037 } |
2037 | 2038 |
2038 | 2039 |
2039 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 2040 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
| 2041 Register object = ToRegister(instr->TempAt(0)); |
| 2042 Register address = ToRegister(instr->TempAt(1)); |
2040 Register value = ToRegister(instr->InputAt(0)); | 2043 Register value = ToRegister(instr->InputAt(0)); |
2041 Operand cell_operand = Operand::Cell(instr->hydrogen()->cell()); | 2044 ASSERT(!value.is(object)); |
| 2045 Handle<JSGlobalPropertyCell> cell_handle(instr->hydrogen()->cell()); |
| 2046 |
| 2047 int offset = JSGlobalPropertyCell::kValueOffset; |
| 2048 __ mov(object, Immediate(cell_handle)); |
2042 | 2049 |
2043 // If the cell we are storing to contains the hole it could have | 2050 // If the cell we are storing to contains the hole it could have |
2044 // been deleted from the property dictionary. In that case, we need | 2051 // been deleted from the property dictionary. In that case, we need |
2045 // to update the property details in the property dictionary to mark | 2052 // to update the property details in the property dictionary to mark |
2046 // it as no longer deleted. We deoptimize in that case. | 2053 // it as no longer deleted. We deoptimize in that case. |
2047 if (instr->hydrogen()->check_hole_value()) { | 2054 if (instr->hydrogen()->check_hole_value()) { |
2048 __ cmp(cell_operand, factory()->the_hole_value()); | 2055 __ cmp(FieldOperand(object, offset), factory()->the_hole_value()); |
2049 DeoptimizeIf(equal, instr->environment()); | 2056 DeoptimizeIf(equal, instr->environment()); |
2050 } | 2057 } |
2051 | 2058 |
2052 // Store the value. | 2059 // Store the value. |
2053 __ mov(cell_operand, value); | 2060 __ mov(FieldOperand(object, offset), value); |
| 2061 |
| 2062 // Cells are always in the remembered set. |
| 2063 __ RecordWriteField(object, |
| 2064 offset, |
| 2065 value, |
| 2066 address, |
| 2067 kSaveFPRegs, |
| 2068 OMIT_REMEMBERED_SET); |
2054 } | 2069 } |
2055 | 2070 |
2056 | 2071 |
2057 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 2072 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
2058 ASSERT(ToRegister(instr->context()).is(esi)); | 2073 ASSERT(ToRegister(instr->context()).is(esi)); |
2059 ASSERT(ToRegister(instr->global_object()).is(edx)); | 2074 ASSERT(ToRegister(instr->global_object()).is(edx)); |
2060 ASSERT(ToRegister(instr->value()).is(eax)); | 2075 ASSERT(ToRegister(instr->value()).is(eax)); |
2061 | 2076 |
2062 __ mov(ecx, instr->name()); | 2077 __ mov(ecx, instr->name()); |
2063 Handle<Code> ic = instr->strict_mode() | 2078 Handle<Code> ic = instr->strict_mode() |
(...skipping 10 matching lines...) Expand all Loading... |
2074 } | 2089 } |
2075 | 2090 |
2076 | 2091 |
2077 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 2092 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
2078 Register context = ToRegister(instr->context()); | 2093 Register context = ToRegister(instr->context()); |
2079 Register value = ToRegister(instr->value()); | 2094 Register value = ToRegister(instr->value()); |
2080 __ mov(ContextOperand(context, instr->slot_index()), value); | 2095 __ mov(ContextOperand(context, instr->slot_index()), value); |
2081 if (instr->needs_write_barrier()) { | 2096 if (instr->needs_write_barrier()) { |
2082 Register temp = ToRegister(instr->TempAt(0)); | 2097 Register temp = ToRegister(instr->TempAt(0)); |
2083 int offset = Context::SlotOffset(instr->slot_index()); | 2098 int offset = Context::SlotOffset(instr->slot_index()); |
2084 __ RecordWrite(context, offset, value, temp); | 2099 __ RecordWriteContextSlot(context, offset, value, temp, kSaveFPRegs); |
2085 } | 2100 } |
2086 } | 2101 } |
2087 | 2102 |
2088 | 2103 |
2089 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2104 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
2090 Register object = ToRegister(instr->object()); | 2105 Register object = ToRegister(instr->object()); |
2091 Register result = ToRegister(instr->result()); | 2106 Register result = ToRegister(instr->result()); |
2092 if (instr->hydrogen()->is_in_object()) { | 2107 if (instr->hydrogen()->is_in_object()) { |
2093 __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); | 2108 __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); |
2094 } else { | 2109 } else { |
(...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3073 if (!instr->transition().is_null()) { | 3088 if (!instr->transition().is_null()) { |
3074 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); | 3089 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); |
3075 } | 3090 } |
3076 | 3091 |
3077 // Do the store. | 3092 // Do the store. |
3078 if (instr->is_in_object()) { | 3093 if (instr->is_in_object()) { |
3079 __ mov(FieldOperand(object, offset), value); | 3094 __ mov(FieldOperand(object, offset), value); |
3080 if (instr->needs_write_barrier()) { | 3095 if (instr->needs_write_barrier()) { |
3081 Register temp = ToRegister(instr->TempAt(0)); | 3096 Register temp = ToRegister(instr->TempAt(0)); |
3082 // Update the write barrier for the object for in-object properties. | 3097 // Update the write barrier for the object for in-object properties. |
3083 __ RecordWrite(object, offset, value, temp); | 3098 __ RecordWriteField(object, offset, value, temp, kSaveFPRegs); |
3084 } | 3099 } |
3085 } else { | 3100 } else { |
3086 Register temp = ToRegister(instr->TempAt(0)); | 3101 Register temp = ToRegister(instr->TempAt(0)); |
3087 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 3102 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); |
3088 __ mov(FieldOperand(temp, offset), value); | 3103 __ mov(FieldOperand(temp, offset), value); |
3089 if (instr->needs_write_barrier()) { | 3104 if (instr->needs_write_barrier()) { |
3090 // Update the write barrier for the properties array. | 3105 // Update the write barrier for the properties array. |
3091 // object is used as a scratch register. | 3106 // object is used as a scratch register. |
3092 __ RecordWrite(temp, offset, value, object); | 3107 __ RecordWriteField(temp, offset, value, object, kSaveFPRegs); |
3093 } | 3108 } |
3094 } | 3109 } |
3095 } | 3110 } |
3096 | 3111 |
3097 | 3112 |
3098 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 3113 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
3099 ASSERT(ToRegister(instr->context()).is(esi)); | 3114 ASSERT(ToRegister(instr->context()).is(esi)); |
3100 ASSERT(ToRegister(instr->object()).is(edx)); | 3115 ASSERT(ToRegister(instr->object()).is(edx)); |
3101 ASSERT(ToRegister(instr->value()).is(eax)); | 3116 ASSERT(ToRegister(instr->value()).is(eax)); |
3102 | 3117 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3179 value); | 3194 value); |
3180 } | 3195 } |
3181 | 3196 |
3182 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3197 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3183 // Compute address of modified element and store it into key register. | 3198 // Compute address of modified element and store it into key register. |
3184 __ lea(key, | 3199 __ lea(key, |
3185 FieldOperand(elements, | 3200 FieldOperand(elements, |
3186 key, | 3201 key, |
3187 times_pointer_size, | 3202 times_pointer_size, |
3188 FixedArray::kHeaderSize)); | 3203 FixedArray::kHeaderSize)); |
3189 __ RecordWrite(elements, key, value); | 3204 __ RecordWrite(elements, key, value, kSaveFPRegs); |
3190 } | 3205 } |
3191 } | 3206 } |
3192 | 3207 |
3193 | 3208 |
3194 void LCodeGen::DoStoreKeyedFastDoubleElement( | 3209 void LCodeGen::DoStoreKeyedFastDoubleElement( |
3195 LStoreKeyedFastDoubleElement* instr) { | 3210 LStoreKeyedFastDoubleElement* instr) { |
3196 XMMRegister value = ToDoubleRegister(instr->value()); | 3211 XMMRegister value = ToDoubleRegister(instr->value()); |
3197 Label have_value; | 3212 Label have_value; |
3198 | 3213 |
3199 __ ucomisd(value, value); | 3214 __ ucomisd(value, value); |
(...skipping 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4396 env->deoptimization_index()); | 4411 env->deoptimization_index()); |
4397 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4412 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
4398 } | 4413 } |
4399 | 4414 |
4400 | 4415 |
4401 #undef __ | 4416 #undef __ |
4402 | 4417 |
4403 } } // namespace v8::internal | 4418 } } // namespace v8::internal |
4404 | 4419 |
4405 #endif // V8_TARGET_ARCH_IA32 | 4420 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |