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 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 // Possibly allocate a local context. | 290 // Possibly allocate a local context. |
291 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 291 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
292 if (heap_slots > 0) { | 292 if (heap_slots > 0) { |
293 Comment(";;; Allocate local context"); | 293 Comment(";;; Allocate local context"); |
294 // Argument to NewContext is the function, which is still in edi. | 294 // Argument to NewContext is the function, which is still in edi. |
295 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 295 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
296 FastNewContextStub stub(heap_slots); | 296 FastNewContextStub stub(heap_slots); |
297 __ CallStub(&stub); | 297 __ CallStub(&stub); |
298 } else { | 298 } else { |
299 __ push(edi); | 299 __ push(edi); |
300 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 300 __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); |
301 } | 301 } |
302 RecordSafepoint(Safepoint::kNoLazyDeopt); | 302 RecordSafepoint(Safepoint::kNoLazyDeopt); |
303 // Context is returned in eax. It replaces the context passed to us. | 303 // Context is returned in eax. It replaces the context passed to us. |
304 // It's saved in the stack and kept live in esi. | 304 // It's saved in the stack and kept live in esi. |
305 __ mov(esi, eax); | 305 __ mov(esi, eax); |
306 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax); | 306 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax); |
307 | 307 |
308 // Copy parameters into context if necessary. | 308 // Copy parameters into context if necessary. |
309 int num_parameters = scope()->num_parameters(); | 309 int num_parameters = scope()->num_parameters(); |
310 for (int i = 0; i < num_parameters; i++) { | 310 for (int i = 0; i < num_parameters; i++) { |
(...skipping 3421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3732 ASSERT(result.is(esi)); | 3732 ASSERT(result.is(esi)); |
3733 } | 3733 } |
3734 } | 3734 } |
3735 | 3735 |
3736 | 3736 |
3737 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3737 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
3738 ASSERT(ToRegister(instr->context()).is(esi)); | 3738 ASSERT(ToRegister(instr->context()).is(esi)); |
3739 __ push(esi); // The context is the first argument. | 3739 __ push(esi); // The context is the first argument. |
3740 __ push(Immediate(instr->hydrogen()->pairs())); | 3740 __ push(Immediate(instr->hydrogen()->pairs())); |
3741 __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags()))); | 3741 __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags()))); |
3742 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3742 CallRuntime(Runtime::kHiddenDeclareGlobals, 3, instr); |
3743 } | 3743 } |
3744 | 3744 |
3745 | 3745 |
3746 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3746 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
3747 int formal_parameter_count, | 3747 int formal_parameter_count, |
3748 int arity, | 3748 int arity, |
3749 LInstruction* instr, | 3749 LInstruction* instr, |
3750 EDIState edi_state) { | 3750 EDIState edi_state) { |
3751 bool dont_adapt_arguments = | 3751 bool dont_adapt_arguments = |
3752 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3752 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3856 // |result| are the same register and |input| will be restored | 3856 // |result| are the same register and |input| will be restored |
3857 // unchanged by popping safepoint registers. | 3857 // unchanged by popping safepoint registers. |
3858 __ test(tmp, Immediate(HeapNumber::kSignMask)); | 3858 __ test(tmp, Immediate(HeapNumber::kSignMask)); |
3859 __ j(zero, &done, Label::kNear); | 3859 __ j(zero, &done, Label::kNear); |
3860 | 3860 |
3861 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); | 3861 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); |
3862 __ jmp(&allocated, Label::kNear); | 3862 __ jmp(&allocated, Label::kNear); |
3863 | 3863 |
3864 // Slow case: Call the runtime system to do the number allocation. | 3864 // Slow case: Call the runtime system to do the number allocation. |
3865 __ bind(&slow); | 3865 __ bind(&slow); |
3866 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, | 3866 CallRuntimeFromDeferred(Runtime::kHiddenAllocateHeapNumber, 0, |
3867 instr, instr->context()); | 3867 instr, instr->context()); |
3868 // Set the pointer to the new heap number in tmp. | 3868 // Set the pointer to the new heap number in tmp. |
3869 if (!tmp.is(eax)) __ mov(tmp, eax); | 3869 if (!tmp.is(eax)) __ mov(tmp, eax); |
3870 // Restore input_reg after call to runtime. | 3870 // Restore input_reg after call to runtime. |
3871 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); | 3871 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); |
3872 | 3872 |
3873 __ bind(&allocated); | 3873 __ bind(&allocated); |
3874 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 3874 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
3875 __ and_(tmp2, ~HeapNumber::kSignMask); | 3875 __ and_(tmp2, ~HeapNumber::kSignMask); |
3876 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); | 3876 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); |
(...skipping 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5017 // TODO(3095996): Put a valid pointer value in the stack slot where the | 5017 // TODO(3095996): Put a valid pointer value in the stack slot where the |
5018 // result register is stored, as this register is in the pointer map, but | 5018 // result register is stored, as this register is in the pointer map, but |
5019 // contains an integer value. | 5019 // contains an integer value. |
5020 __ Move(reg, Immediate(0)); | 5020 __ Move(reg, Immediate(0)); |
5021 | 5021 |
5022 // Preserve the value of all registers. | 5022 // Preserve the value of all registers. |
5023 PushSafepointRegistersScope scope(this); | 5023 PushSafepointRegistersScope scope(this); |
5024 | 5024 |
5025 // NumberTagI and NumberTagD use the context from the frame, rather than | 5025 // NumberTagI and NumberTagD use the context from the frame, rather than |
5026 // the environment's HContext or HInlinedContext value. | 5026 // the environment's HContext or HInlinedContext value. |
5027 // They only call Runtime::kAllocateHeapNumber. | 5027 // They only call Runtime::kHiddenAllocateHeapNumber. |
5028 // The corresponding HChange instructions are added in a phase that does | 5028 // The corresponding HChange instructions are added in a phase that does |
5029 // not have easy access to the local context. | 5029 // not have easy access to the local context. |
5030 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 5030 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
5031 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 5031 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); |
5032 RecordSafepointWithRegisters( | 5032 RecordSafepointWithRegisters( |
5033 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 5033 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
5034 __ StoreToSafepointRegisterSlot(reg, eax); | 5034 __ StoreToSafepointRegisterSlot(reg, eax); |
5035 } | 5035 } |
5036 | 5036 |
5037 // Done. Put the value in xmm_scratch into the value of the allocated heap | 5037 // Done. Put the value in xmm_scratch into the value of the allocated heap |
5038 // number. | 5038 // number. |
5039 __ bind(&done); | 5039 __ bind(&done); |
5040 if (CpuFeatures::IsSupported(SSE2)) { | 5040 if (CpuFeatures::IsSupported(SSE2)) { |
5041 CpuFeatureScope feature_scope(masm(), SSE2); | 5041 CpuFeatureScope feature_scope(masm(), SSE2); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5092 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 5092 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
5093 // TODO(3095996): Get rid of this. For now, we need to make the | 5093 // TODO(3095996): Get rid of this. For now, we need to make the |
5094 // result register contain a valid pointer because it is already | 5094 // result register contain a valid pointer because it is already |
5095 // contained in the register pointer map. | 5095 // contained in the register pointer map. |
5096 Register reg = ToRegister(instr->result()); | 5096 Register reg = ToRegister(instr->result()); |
5097 __ Move(reg, Immediate(0)); | 5097 __ Move(reg, Immediate(0)); |
5098 | 5098 |
5099 PushSafepointRegistersScope scope(this); | 5099 PushSafepointRegistersScope scope(this); |
5100 // NumberTagI and NumberTagD use the context from the frame, rather than | 5100 // NumberTagI and NumberTagD use the context from the frame, rather than |
5101 // the environment's HContext or HInlinedContext value. | 5101 // the environment's HContext or HInlinedContext value. |
5102 // They only call Runtime::kAllocateHeapNumber. | 5102 // They only call Runtime::kHiddenAllocateHeapNumber. |
5103 // The corresponding HChange instructions are added in a phase that does | 5103 // The corresponding HChange instructions are added in a phase that does |
5104 // not have easy access to the local context. | 5104 // not have easy access to the local context. |
5105 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 5105 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
5106 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 5106 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); |
5107 RecordSafepointWithRegisters( | 5107 RecordSafepointWithRegisters( |
5108 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 5108 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
5109 __ StoreToSafepointRegisterSlot(reg, eax); | 5109 __ StoreToSafepointRegisterSlot(reg, eax); |
5110 } | 5110 } |
5111 | 5111 |
5112 | 5112 |
5113 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 5113 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
5114 HChange* hchange = instr->hydrogen(); | 5114 HChange* hchange = instr->hydrogen(); |
5115 Register input = ToRegister(instr->value()); | 5115 Register input = ToRegister(instr->value()); |
5116 if (hchange->CheckFlag(HValue::kCanOverflow) && | 5116 if (hchange->CheckFlag(HValue::kCanOverflow) && |
(...skipping 802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5919 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); | 5919 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); |
5920 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5920 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
5921 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5921 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
5922 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); | 5922 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); |
5923 } else { | 5923 } else { |
5924 flags = AllocateTargetSpace::update(flags, NEW_SPACE); | 5924 flags = AllocateTargetSpace::update(flags, NEW_SPACE); |
5925 } | 5925 } |
5926 __ push(Immediate(Smi::FromInt(flags))); | 5926 __ push(Immediate(Smi::FromInt(flags))); |
5927 | 5927 |
5928 CallRuntimeFromDeferred( | 5928 CallRuntimeFromDeferred( |
5929 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); | 5929 Runtime::kHiddenAllocateInTargetSpace, 2, instr, instr->context()); |
5930 __ StoreToSafepointRegisterSlot(result, eax); | 5930 __ StoreToSafepointRegisterSlot(result, eax); |
5931 } | 5931 } |
5932 | 5932 |
5933 | 5933 |
5934 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5934 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
5935 ASSERT(ToRegister(instr->value()).is(eax)); | 5935 ASSERT(ToRegister(instr->value()).is(eax)); |
5936 __ push(eax); | 5936 __ push(eax); |
5937 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5937 CallRuntime(Runtime::kToFastProperties, 1, instr); |
5938 } | 5938 } |
5939 | 5939 |
(...skipping 12 matching lines...) Expand all Loading... |
5952 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 5952 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
5953 __ cmp(ebx, factory()->undefined_value()); | 5953 __ cmp(ebx, factory()->undefined_value()); |
5954 __ j(not_equal, &materialized, Label::kNear); | 5954 __ j(not_equal, &materialized, Label::kNear); |
5955 | 5955 |
5956 // Create regexp literal using runtime function | 5956 // Create regexp literal using runtime function |
5957 // Result will be in eax. | 5957 // Result will be in eax. |
5958 __ push(ecx); | 5958 __ push(ecx); |
5959 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 5959 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
5960 __ push(Immediate(instr->hydrogen()->pattern())); | 5960 __ push(Immediate(instr->hydrogen()->pattern())); |
5961 __ push(Immediate(instr->hydrogen()->flags())); | 5961 __ push(Immediate(instr->hydrogen()->flags())); |
5962 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); | 5962 CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4, instr); |
5963 __ mov(ebx, eax); | 5963 __ mov(ebx, eax); |
5964 | 5964 |
5965 __ bind(&materialized); | 5965 __ bind(&materialized); |
5966 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 5966 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
5967 Label allocated, runtime_allocate; | 5967 Label allocated, runtime_allocate; |
5968 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); | 5968 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); |
5969 __ jmp(&allocated, Label::kNear); | 5969 __ jmp(&allocated, Label::kNear); |
5970 | 5970 |
5971 __ bind(&runtime_allocate); | 5971 __ bind(&runtime_allocate); |
5972 __ push(ebx); | 5972 __ push(ebx); |
5973 __ push(Immediate(Smi::FromInt(size))); | 5973 __ push(Immediate(Smi::FromInt(size))); |
5974 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); | 5974 CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1, instr); |
5975 __ pop(ebx); | 5975 __ pop(ebx); |
5976 | 5976 |
5977 __ bind(&allocated); | 5977 __ bind(&allocated); |
5978 // Copy the content into the newly allocated memory. | 5978 // Copy the content into the newly allocated memory. |
5979 // (Unroll copy loop once for better throughput). | 5979 // (Unroll copy loop once for better throughput). |
5980 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { | 5980 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { |
5981 __ mov(edx, FieldOperand(ebx, i)); | 5981 __ mov(edx, FieldOperand(ebx, i)); |
5982 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); | 5982 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); |
5983 __ mov(FieldOperand(eax, i), edx); | 5983 __ mov(FieldOperand(eax, i), edx); |
5984 __ mov(FieldOperand(eax, i + kPointerSize), ecx); | 5984 __ mov(FieldOperand(eax, i + kPointerSize), ecx); |
(...skipping 13 matching lines...) Expand all Loading... |
5998 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 5998 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
5999 FastNewClosureStub stub(instr->hydrogen()->strict_mode(), | 5999 FastNewClosureStub stub(instr->hydrogen()->strict_mode(), |
6000 instr->hydrogen()->is_generator()); | 6000 instr->hydrogen()->is_generator()); |
6001 __ mov(ebx, Immediate(instr->hydrogen()->shared_info())); | 6001 __ mov(ebx, Immediate(instr->hydrogen()->shared_info())); |
6002 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 6002 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
6003 } else { | 6003 } else { |
6004 __ push(esi); | 6004 __ push(esi); |
6005 __ push(Immediate(instr->hydrogen()->shared_info())); | 6005 __ push(Immediate(instr->hydrogen()->shared_info())); |
6006 __ push(Immediate(pretenure ? factory()->true_value() | 6006 __ push(Immediate(pretenure ? factory()->true_value() |
6007 : factory()->false_value())); | 6007 : factory()->false_value())); |
6008 CallRuntime(Runtime::kNewClosure, 3, instr); | 6008 CallRuntime(Runtime::kHiddenNewClosure, 3, instr); |
6009 } | 6009 } |
6010 } | 6010 } |
6011 | 6011 |
6012 | 6012 |
6013 void LCodeGen::DoTypeof(LTypeof* instr) { | 6013 void LCodeGen::DoTypeof(LTypeof* instr) { |
6014 ASSERT(ToRegister(instr->context()).is(esi)); | 6014 ASSERT(ToRegister(instr->context()).is(esi)); |
6015 LOperand* input = instr->value(); | 6015 LOperand* input = instr->value(); |
6016 EmitPushTaggedOperand(input); | 6016 EmitPushTaggedOperand(input); |
6017 CallRuntime(Runtime::kTypeof, 1, instr); | 6017 CallRuntime(Runtime::kTypeof, 1, instr); |
6018 } | 6018 } |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6178 | 6178 |
6179 | 6179 |
6180 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 6180 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
6181 // Nothing to see here, move on! | 6181 // Nothing to see here, move on! |
6182 } | 6182 } |
6183 | 6183 |
6184 | 6184 |
6185 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 6185 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
6186 PushSafepointRegistersScope scope(this); | 6186 PushSafepointRegistersScope scope(this); |
6187 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 6187 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
6188 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 6188 __ CallRuntimeSaveDoubles(Runtime::kHiddenStackGuard); |
6189 RecordSafepointWithLazyDeopt( | 6189 RecordSafepointWithLazyDeopt( |
6190 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 6190 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
6191 ASSERT(instr->HasEnvironment()); | 6191 ASSERT(instr->HasEnvironment()); |
6192 LEnvironment* env = instr->environment(); | 6192 LEnvironment* env = instr->environment(); |
6193 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 6193 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
6194 } | 6194 } |
6195 | 6195 |
6196 | 6196 |
6197 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 6197 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
6198 class DeferredStackCheck V8_FINAL : public LDeferredCode { | 6198 class DeferredStackCheck V8_FINAL : public LDeferredCode { |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6348 FixedArray::kHeaderSize - kPointerSize)); | 6348 FixedArray::kHeaderSize - kPointerSize)); |
6349 __ bind(&done); | 6349 __ bind(&done); |
6350 } | 6350 } |
6351 | 6351 |
6352 | 6352 |
6353 #undef __ | 6353 #undef __ |
6354 | 6354 |
6355 } } // namespace v8::internal | 6355 } } // namespace v8::internal |
6356 | 6356 |
6357 #endif // V8_TARGET_ARCH_IA32 | 6357 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |