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 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 // Possibly allocate a local context. | 204 // Possibly allocate a local context. |
205 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 205 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
206 if (heap_slots > 0) { | 206 if (heap_slots > 0) { |
207 Comment(";;; Allocate local context"); | 207 Comment(";;; Allocate local context"); |
208 // Argument to NewContext is the function, which is in r1. | 208 // Argument to NewContext is the function, which is in r1. |
209 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 209 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
210 FastNewContextStub stub(heap_slots); | 210 FastNewContextStub stub(heap_slots); |
211 __ CallStub(&stub); | 211 __ CallStub(&stub); |
212 } else { | 212 } else { |
213 __ push(r1); | 213 __ push(r1); |
214 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 214 __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); |
215 } | 215 } |
216 RecordSafepoint(Safepoint::kNoLazyDeopt); | 216 RecordSafepoint(Safepoint::kNoLazyDeopt); |
217 // Context is returned in both r0 and cp. It replaces the context | 217 // Context is returned in both r0 and cp. It replaces the context |
218 // passed to us. It's saved in the stack and kept live in cp. | 218 // passed to us. It's saved in the stack and kept live in cp. |
219 __ mov(cp, r0); | 219 __ mov(cp, r0); |
220 __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 220 __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
221 // Copy any necessary parameters into the context. | 221 // Copy any necessary parameters into the context. |
222 int num_parameters = scope()->num_parameters(); | 222 int num_parameters = scope()->num_parameters(); |
223 for (int i = 0; i < num_parameters; i++) { | 223 for (int i = 0; i < num_parameters; i++) { |
224 Variable* var = scope()->parameter(i); | 224 Variable* var = scope()->parameter(i); |
(...skipping 3307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3532 } | 3532 } |
3533 | 3533 |
3534 | 3534 |
3535 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3535 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
3536 ASSERT(ToRegister(instr->context()).is(cp)); | 3536 ASSERT(ToRegister(instr->context()).is(cp)); |
3537 __ push(cp); // The context is the first argument. | 3537 __ push(cp); // The context is the first argument. |
3538 __ Move(scratch0(), instr->hydrogen()->pairs()); | 3538 __ Move(scratch0(), instr->hydrogen()->pairs()); |
3539 __ push(scratch0()); | 3539 __ push(scratch0()); |
3540 __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); | 3540 __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); |
3541 __ push(scratch0()); | 3541 __ push(scratch0()); |
3542 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3542 CallRuntime(Runtime::kHiddenDeclareGlobals, 3, instr); |
3543 } | 3543 } |
3544 | 3544 |
3545 | 3545 |
3546 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3546 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
3547 int formal_parameter_count, | 3547 int formal_parameter_count, |
3548 int arity, | 3548 int arity, |
3549 LInstruction* instr, | 3549 LInstruction* instr, |
3550 R1State r1_state) { | 3550 R1State r1_state) { |
3551 bool dont_adapt_arguments = | 3551 bool dont_adapt_arguments = |
3552 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3552 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3623 // exponent: floating point exponent value. | 3623 // exponent: floating point exponent value. |
3624 | 3624 |
3625 Label allocated, slow; | 3625 Label allocated, slow; |
3626 __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex); | 3626 __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex); |
3627 __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow); | 3627 __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow); |
3628 __ b(&allocated); | 3628 __ b(&allocated); |
3629 | 3629 |
3630 // Slow case: Call the runtime system to do the number allocation. | 3630 // Slow case: Call the runtime system to do the number allocation. |
3631 __ bind(&slow); | 3631 __ bind(&slow); |
3632 | 3632 |
3633 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr, | 3633 CallRuntimeFromDeferred(Runtime::kHiddenAllocateHeapNumber, 0, instr, |
3634 instr->context()); | 3634 instr->context()); |
3635 // Set the pointer to the new heap number in tmp. | 3635 // Set the pointer to the new heap number in tmp. |
3636 if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0)); | 3636 if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0)); |
3637 // Restore input_reg after call to runtime. | 3637 // Restore input_reg after call to runtime. |
3638 __ LoadFromSafepointRegisterSlot(input, input); | 3638 __ LoadFromSafepointRegisterSlot(input, input); |
3639 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 3639 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
3640 | 3640 |
3641 __ bind(&allocated); | 3641 __ bind(&allocated); |
3642 // exponent: floating point exponent value. | 3642 // exponent: floating point exponent value. |
3643 // tmp1: allocated heap number. | 3643 // tmp1: allocated heap number. |
(...skipping 999 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4643 // TODO(3095996): Put a valid pointer value in the stack slot where the | 4643 // TODO(3095996): Put a valid pointer value in the stack slot where the |
4644 // result register is stored, as this register is in the pointer map, but | 4644 // result register is stored, as this register is in the pointer map, but |
4645 // contains an integer value. | 4645 // contains an integer value. |
4646 __ mov(dst, Operand::Zero()); | 4646 __ mov(dst, Operand::Zero()); |
4647 | 4647 |
4648 // Preserve the value of all registers. | 4648 // Preserve the value of all registers. |
4649 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4649 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4650 | 4650 |
4651 // NumberTagI and NumberTagD use the context from the frame, rather than | 4651 // NumberTagI and NumberTagD use the context from the frame, rather than |
4652 // the environment's HContext or HInlinedContext value. | 4652 // the environment's HContext or HInlinedContext value. |
4653 // They only call Runtime::kAllocateHeapNumber. | 4653 // They only call Runtime::kHiddenAllocateHeapNumber. |
4654 // The corresponding HChange instructions are added in a phase that does | 4654 // The corresponding HChange instructions are added in a phase that does |
4655 // not have easy access to the local context. | 4655 // not have easy access to the local context. |
4656 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4656 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
4657 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 4657 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); |
4658 RecordSafepointWithRegisters( | 4658 RecordSafepointWithRegisters( |
4659 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4659 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
4660 __ sub(r0, r0, Operand(kHeapObjectTag)); | 4660 __ sub(r0, r0, Operand(kHeapObjectTag)); |
4661 __ StoreToSafepointRegisterSlot(r0, dst); | 4661 __ StoreToSafepointRegisterSlot(r0, dst); |
4662 } | 4662 } |
4663 | 4663 |
4664 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4664 // Done. Put the value in dbl_scratch into the value of the allocated heap |
4665 // number. | 4665 // number. |
4666 __ bind(&done); | 4666 __ bind(&done); |
4667 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); | 4667 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4707 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4707 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
4708 // TODO(3095996): Get rid of this. For now, we need to make the | 4708 // TODO(3095996): Get rid of this. For now, we need to make the |
4709 // result register contain a valid pointer because it is already | 4709 // result register contain a valid pointer because it is already |
4710 // contained in the register pointer map. | 4710 // contained in the register pointer map. |
4711 Register reg = ToRegister(instr->result()); | 4711 Register reg = ToRegister(instr->result()); |
4712 __ mov(reg, Operand::Zero()); | 4712 __ mov(reg, Operand::Zero()); |
4713 | 4713 |
4714 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4714 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4715 // NumberTagI and NumberTagD use the context from the frame, rather than | 4715 // NumberTagI and NumberTagD use the context from the frame, rather than |
4716 // the environment's HContext or HInlinedContext value. | 4716 // the environment's HContext or HInlinedContext value. |
4717 // They only call Runtime::kAllocateHeapNumber. | 4717 // They only call Runtime::kHiddenAllocateHeapNumber. |
4718 // The corresponding HChange instructions are added in a phase that does | 4718 // The corresponding HChange instructions are added in a phase that does |
4719 // not have easy access to the local context. | 4719 // not have easy access to the local context. |
4720 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4720 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
4721 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 4721 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); |
4722 RecordSafepointWithRegisters( | 4722 RecordSafepointWithRegisters( |
4723 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4723 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
4724 __ sub(r0, r0, Operand(kHeapObjectTag)); | 4724 __ sub(r0, r0, Operand(kHeapObjectTag)); |
4725 __ StoreToSafepointRegisterSlot(r0, reg); | 4725 __ StoreToSafepointRegisterSlot(r0, reg); |
4726 } | 4726 } |
4727 | 4727 |
4728 | 4728 |
4729 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4729 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4730 HChange* hchange = instr->hydrogen(); | 4730 HChange* hchange = instr->hydrogen(); |
4731 Register input = ToRegister(instr->value()); | 4731 Register input = ToRegister(instr->value()); |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5312 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); | 5312 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); |
5313 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5313 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
5314 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5314 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
5315 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); | 5315 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); |
5316 } else { | 5316 } else { |
5317 flags = AllocateTargetSpace::update(flags, NEW_SPACE); | 5317 flags = AllocateTargetSpace::update(flags, NEW_SPACE); |
5318 } | 5318 } |
5319 __ Push(Smi::FromInt(flags)); | 5319 __ Push(Smi::FromInt(flags)); |
5320 | 5320 |
5321 CallRuntimeFromDeferred( | 5321 CallRuntimeFromDeferred( |
5322 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); | 5322 Runtime::kHiddenAllocateInTargetSpace, 2, instr, instr->context()); |
5323 __ StoreToSafepointRegisterSlot(r0, result); | 5323 __ StoreToSafepointRegisterSlot(r0, result); |
5324 } | 5324 } |
5325 | 5325 |
5326 | 5326 |
5327 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5327 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
5328 ASSERT(ToRegister(instr->value()).is(r0)); | 5328 ASSERT(ToRegister(instr->value()).is(r0)); |
5329 __ push(r0); | 5329 __ push(r0); |
5330 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5330 CallRuntime(Runtime::kToFastProperties, 1, instr); |
5331 } | 5331 } |
5332 | 5332 |
(...skipping 13 matching lines...) Expand all Loading... |
5346 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 5346 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
5347 __ cmp(r1, ip); | 5347 __ cmp(r1, ip); |
5348 __ b(ne, &materialized); | 5348 __ b(ne, &materialized); |
5349 | 5349 |
5350 // Create regexp literal using runtime function | 5350 // Create regexp literal using runtime function |
5351 // Result will be in r0. | 5351 // Result will be in r0. |
5352 __ mov(r5, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); | 5352 __ mov(r5, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); |
5353 __ mov(r4, Operand(instr->hydrogen()->pattern())); | 5353 __ mov(r4, Operand(instr->hydrogen()->pattern())); |
5354 __ mov(r3, Operand(instr->hydrogen()->flags())); | 5354 __ mov(r3, Operand(instr->hydrogen()->flags())); |
5355 __ Push(r6, r5, r4, r3); | 5355 __ Push(r6, r5, r4, r3); |
5356 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); | 5356 CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4, instr); |
5357 __ mov(r1, r0); | 5357 __ mov(r1, r0); |
5358 | 5358 |
5359 __ bind(&materialized); | 5359 __ bind(&materialized); |
5360 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 5360 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
5361 Label allocated, runtime_allocate; | 5361 Label allocated, runtime_allocate; |
5362 | 5362 |
5363 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); | 5363 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); |
5364 __ jmp(&allocated); | 5364 __ jmp(&allocated); |
5365 | 5365 |
5366 __ bind(&runtime_allocate); | 5366 __ bind(&runtime_allocate); |
5367 __ mov(r0, Operand(Smi::FromInt(size))); | 5367 __ mov(r0, Operand(Smi::FromInt(size))); |
5368 __ Push(r1, r0); | 5368 __ Push(r1, r0); |
5369 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); | 5369 CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1, instr); |
5370 __ pop(r1); | 5370 __ pop(r1); |
5371 | 5371 |
5372 __ bind(&allocated); | 5372 __ bind(&allocated); |
5373 // Copy the content into the newly allocated memory. | 5373 // Copy the content into the newly allocated memory. |
5374 __ CopyFields(r0, r1, double_scratch0(), size / kPointerSize); | 5374 __ CopyFields(r0, r1, double_scratch0(), size / kPointerSize); |
5375 } | 5375 } |
5376 | 5376 |
5377 | 5377 |
5378 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 5378 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
5379 ASSERT(ToRegister(instr->context()).is(cp)); | 5379 ASSERT(ToRegister(instr->context()).is(cp)); |
5380 // Use the fast case closure allocation code that allocates in new | 5380 // Use the fast case closure allocation code that allocates in new |
5381 // space for nested functions that don't need literals cloning. | 5381 // space for nested functions that don't need literals cloning. |
5382 bool pretenure = instr->hydrogen()->pretenure(); | 5382 bool pretenure = instr->hydrogen()->pretenure(); |
5383 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 5383 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
5384 FastNewClosureStub stub(instr->hydrogen()->strict_mode(), | 5384 FastNewClosureStub stub(instr->hydrogen()->strict_mode(), |
5385 instr->hydrogen()->is_generator()); | 5385 instr->hydrogen()->is_generator()); |
5386 __ mov(r2, Operand(instr->hydrogen()->shared_info())); | 5386 __ mov(r2, Operand(instr->hydrogen()->shared_info())); |
5387 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 5387 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
5388 } else { | 5388 } else { |
5389 __ mov(r2, Operand(instr->hydrogen()->shared_info())); | 5389 __ mov(r2, Operand(instr->hydrogen()->shared_info())); |
5390 __ mov(r1, Operand(pretenure ? factory()->true_value() | 5390 __ mov(r1, Operand(pretenure ? factory()->true_value() |
5391 : factory()->false_value())); | 5391 : factory()->false_value())); |
5392 __ Push(cp, r2, r1); | 5392 __ Push(cp, r2, r1); |
5393 CallRuntime(Runtime::kNewClosure, 3, instr); | 5393 CallRuntime(Runtime::kHiddenNewClosure, 3, instr); |
5394 } | 5394 } |
5395 } | 5395 } |
5396 | 5396 |
5397 | 5397 |
5398 void LCodeGen::DoTypeof(LTypeof* instr) { | 5398 void LCodeGen::DoTypeof(LTypeof* instr) { |
5399 Register input = ToRegister(instr->value()); | 5399 Register input = ToRegister(instr->value()); |
5400 __ push(input); | 5400 __ push(input); |
5401 CallRuntime(Runtime::kTypeof, 1, instr); | 5401 CallRuntime(Runtime::kTypeof, 1, instr); |
5402 } | 5402 } |
5403 | 5403 |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5568 | 5568 |
5569 | 5569 |
5570 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5570 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
5571 // Nothing to see here, move on! | 5571 // Nothing to see here, move on! |
5572 } | 5572 } |
5573 | 5573 |
5574 | 5574 |
5575 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 5575 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
5576 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5576 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
5577 LoadContextFromDeferred(instr->context()); | 5577 LoadContextFromDeferred(instr->context()); |
5578 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 5578 __ CallRuntimeSaveDoubles(Runtime::kHiddenStackGuard); |
5579 RecordSafepointWithLazyDeopt( | 5579 RecordSafepointWithLazyDeopt( |
5580 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 5580 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
5581 ASSERT(instr->HasEnvironment()); | 5581 ASSERT(instr->HasEnvironment()); |
5582 LEnvironment* env = instr->environment(); | 5582 LEnvironment* env = instr->environment(); |
5583 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5583 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
5584 } | 5584 } |
5585 | 5585 |
5586 | 5586 |
5587 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 5587 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
5588 class DeferredStackCheck V8_FINAL : public LDeferredCode { | 5588 class DeferredStackCheck V8_FINAL : public LDeferredCode { |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5738 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5738 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
5739 __ ldr(result, FieldMemOperand(scratch, | 5739 __ ldr(result, FieldMemOperand(scratch, |
5740 FixedArray::kHeaderSize - kPointerSize)); | 5740 FixedArray::kHeaderSize - kPointerSize)); |
5741 __ bind(&done); | 5741 __ bind(&done); |
5742 } | 5742 } |
5743 | 5743 |
5744 | 5744 |
5745 #undef __ | 5745 #undef __ |
5746 | 5746 |
5747 } } // namespace v8::internal | 5747 } } // namespace v8::internal |
OLD | NEW |