| 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 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 | 566 |
| 567 | 567 |
| 568 MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const { | 568 MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const { |
| 569 ASSERT(op->IsDoubleStackSlot()); | 569 ASSERT(op->IsDoubleStackSlot()); |
| 570 return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize); | 570 return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize); |
| 571 } | 571 } |
| 572 | 572 |
| 573 | 573 |
| 574 void LCodeGen::WriteTranslation(LEnvironment* environment, | 574 void LCodeGen::WriteTranslation(LEnvironment* environment, |
| 575 Translation* translation, | 575 Translation* translation, |
| 576 int* arguments_index, | 576 int* pushed_arguments_index, |
| 577 int* arguments_count) { | 577 int* pushed_arguments_count) { |
| 578 if (environment == NULL) return; | 578 if (environment == NULL) return; |
| 579 | 579 |
| 580 // The translation includes one command per value in the environment. | 580 // The translation includes one command per value in the environment. |
| 581 int translation_size = environment->values()->length(); | 581 int translation_size = environment->values()->length(); |
| 582 // The output frame height does not include the parameters. | 582 // The output frame height does not include the parameters. |
| 583 int height = translation_size - environment->parameter_count(); | 583 int height = translation_size - environment->parameter_count(); |
| 584 | 584 |
| 585 // Function parameters are arguments to the outermost environment. The | 585 // Function parameters are arguments to the outermost environment. The |
| 586 // arguments index points to the first element of a sequence of tagged | 586 // arguments index points to the first element of a sequence of tagged |
| 587 // values on the stack that represent the arguments. This needs to be | 587 // values on the stack that represent the arguments. This needs to be |
| 588 // kept in sync with the LArgumentsElements implementation. | 588 // kept in sync with the LArgumentsElements implementation. |
| 589 *arguments_index = -environment->parameter_count(); | 589 *pushed_arguments_index = -environment->parameter_count(); |
| 590 *arguments_count = environment->parameter_count(); | 590 *pushed_arguments_count = environment->parameter_count(); |
| 591 | 591 |
| 592 WriteTranslation(environment->outer(), | 592 WriteTranslation(environment->outer(), |
| 593 translation, | 593 translation, |
| 594 arguments_index, | 594 pushed_arguments_index, |
| 595 arguments_count); | 595 pushed_arguments_count); |
| 596 bool has_closure_id = !info()->closure().is_null() && | 596 bool has_closure_id = !info()->closure().is_null() && |
| 597 *info()->closure() != *environment->closure(); | 597 *info()->closure() != *environment->closure(); |
| 598 int closure_id = has_closure_id | 598 int closure_id = has_closure_id |
| 599 ? DefineDeoptimizationLiteral(environment->closure()) | 599 ? DefineDeoptimizationLiteral(environment->closure()) |
| 600 : Translation::kSelfLiteralId; | 600 : Translation::kSelfLiteralId; |
| 601 | 601 |
| 602 switch (environment->frame_type()) { | 602 switch (environment->frame_type()) { |
| 603 case JS_FUNCTION: | 603 case JS_FUNCTION: |
| 604 translation->BeginJSFrame(environment->ast_id(), closure_id, height); | 604 translation->BeginJSFrame(environment->ast_id(), closure_id, height); |
| 605 break; | 605 break; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 618 break; | 618 break; |
| 619 case STUB: | 619 case STUB: |
| 620 translation->BeginCompiledStubFrame(); | 620 translation->BeginCompiledStubFrame(); |
| 621 break; | 621 break; |
| 622 case ARGUMENTS_ADAPTOR: | 622 case ARGUMENTS_ADAPTOR: |
| 623 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); | 623 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); |
| 624 break; | 624 break; |
| 625 } | 625 } |
| 626 | 626 |
| 627 // Inlined frames which push their arguments cause the index to be | 627 // Inlined frames which push their arguments cause the index to be |
| 628 // bumped and a new stack area to be used for materialization. | 628 // bumped and another stack area to be used for materialization, |
| 629 if (environment->entry() != NULL && | 629 // otherwise actual argument values are unknown for inlined frames. |
| 630 environment->entry()->arguments_pushed()) { | 630 bool arguments_known = true; |
| 631 *arguments_index = *arguments_index < 0 | 631 int arguments_index = *pushed_arguments_index; |
| 632 ? GetStackSlotCount() | 632 int arguments_count = *pushed_arguments_count; |
| 633 : *arguments_index + *arguments_count; | 633 if (environment->entry() != NULL) { |
| 634 *arguments_count = environment->entry()->arguments_count() + 1; | 634 arguments_known = environment->entry()->arguments_pushed(); |
| 635 arguments_index = arguments_index < 0 |
| 636 ? GetStackSlotCount() : arguments_index + arguments_count; |
| 637 arguments_count = environment->entry()->arguments_count() + 1; |
| 638 if (environment->entry()->arguments_pushed()) { |
| 639 *pushed_arguments_index = arguments_index; |
| 640 *pushed_arguments_count = arguments_count; |
| 641 } |
| 635 } | 642 } |
| 636 | 643 |
| 637 for (int i = 0; i < translation_size; ++i) { | 644 for (int i = 0; i < translation_size; ++i) { |
| 638 LOperand* value = environment->values()->at(i); | 645 LOperand* value = environment->values()->at(i); |
| 639 // spilled_registers_ and spilled_double_registers_ are either | 646 // spilled_registers_ and spilled_double_registers_ are either |
| 640 // both NULL or both set. | 647 // both NULL or both set. |
| 641 if (environment->spilled_registers() != NULL && value != NULL) { | 648 if (environment->spilled_registers() != NULL && value != NULL) { |
| 642 if (value->IsRegister() && | 649 if (value->IsRegister() && |
| 643 environment->spilled_registers()[value->index()] != NULL) { | 650 environment->spilled_registers()[value->index()] != NULL) { |
| 644 translation->MarkDuplicate(); | 651 translation->MarkDuplicate(); |
| 645 AddToTranslation(translation, | 652 AddToTranslation(translation, |
| 646 environment->spilled_registers()[value->index()], | 653 environment->spilled_registers()[value->index()], |
| 647 environment->HasTaggedValueAt(i), | 654 environment->HasTaggedValueAt(i), |
| 648 environment->HasUint32ValueAt(i), | 655 environment->HasUint32ValueAt(i), |
| 649 *arguments_index, | 656 arguments_known, |
| 650 *arguments_count); | 657 arguments_index, |
| 658 arguments_count); |
| 651 } else if ( | 659 } else if ( |
| 652 value->IsDoubleRegister() && | 660 value->IsDoubleRegister() && |
| 653 environment->spilled_double_registers()[value->index()] != NULL) { | 661 environment->spilled_double_registers()[value->index()] != NULL) { |
| 654 translation->MarkDuplicate(); | 662 translation->MarkDuplicate(); |
| 655 AddToTranslation( | 663 AddToTranslation( |
| 656 translation, | 664 translation, |
| 657 environment->spilled_double_registers()[value->index()], | 665 environment->spilled_double_registers()[value->index()], |
| 658 false, | 666 false, |
| 659 false, | 667 false, |
| 660 *arguments_index, | 668 arguments_known, |
| 661 *arguments_count); | 669 arguments_index, |
| 670 arguments_count); |
| 662 } | 671 } |
| 663 } | 672 } |
| 664 | 673 |
| 665 AddToTranslation(translation, | 674 AddToTranslation(translation, |
| 666 value, | 675 value, |
| 667 environment->HasTaggedValueAt(i), | 676 environment->HasTaggedValueAt(i), |
| 668 environment->HasUint32ValueAt(i), | 677 environment->HasUint32ValueAt(i), |
| 669 *arguments_index, | 678 arguments_known, |
| 670 *arguments_count); | 679 arguments_index, |
| 680 arguments_count); |
| 671 } | 681 } |
| 672 } | 682 } |
| 673 | 683 |
| 674 | 684 |
| 675 void LCodeGen::AddToTranslation(Translation* translation, | 685 void LCodeGen::AddToTranslation(Translation* translation, |
| 676 LOperand* op, | 686 LOperand* op, |
| 677 bool is_tagged, | 687 bool is_tagged, |
| 678 bool is_uint32, | 688 bool is_uint32, |
| 689 bool arguments_known, |
| 679 int arguments_index, | 690 int arguments_index, |
| 680 int arguments_count) { | 691 int arguments_count) { |
| 681 if (op == NULL) { | 692 if (op == NULL) { |
| 682 // TODO(twuerthinger): Introduce marker operands to indicate that this value | 693 // TODO(twuerthinger): Introduce marker operands to indicate that this value |
| 683 // is not present and must be reconstructed from the deoptimizer. Currently | 694 // is not present and must be reconstructed from the deoptimizer. Currently |
| 684 // this is only used for the arguments object. | 695 // this is only used for the arguments object. |
| 685 translation->StoreArgumentsObject(arguments_index, arguments_count); | 696 translation->StoreArgumentsObject( |
| 697 arguments_known, arguments_index, arguments_count); |
| 686 } else if (op->IsStackSlot()) { | 698 } else if (op->IsStackSlot()) { |
| 687 if (is_tagged) { | 699 if (is_tagged) { |
| 688 translation->StoreStackSlot(op->index()); | 700 translation->StoreStackSlot(op->index()); |
| 689 } else if (is_uint32) { | 701 } else if (is_uint32) { |
| 690 translation->StoreUint32StackSlot(op->index()); | 702 translation->StoreUint32StackSlot(op->index()); |
| 691 } else { | 703 } else { |
| 692 translation->StoreInt32StackSlot(op->index()); | 704 translation->StoreInt32StackSlot(op->index()); |
| 693 } | 705 } |
| 694 } else if (op->IsDoubleStackSlot()) { | 706 } else if (op->IsDoubleStackSlot()) { |
| 695 translation->StoreDoubleStackSlot(op->index()); | 707 translation->StoreDoubleStackSlot(op->index()); |
| (...skipping 1793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2489 instr, | 2501 instr, |
| 2490 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 2502 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 2491 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); | 2503 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); |
| 2492 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 2504 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 2493 // Put the result value into the result register slot and | 2505 // Put the result value into the result register slot and |
| 2494 // restore all registers. | 2506 // restore all registers. |
| 2495 __ StoreToSafepointRegisterSlot(result, result); | 2507 __ StoreToSafepointRegisterSlot(result, result); |
| 2496 } | 2508 } |
| 2497 | 2509 |
| 2498 | 2510 |
| 2511 void LCodeGen::DoInstanceSize(LInstanceSize* instr) { |
| 2512 Register object = ToRegister(instr->object()); |
| 2513 Register result = ToRegister(instr->result()); |
| 2514 __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 2515 __ lbu(result, FieldMemOperand(result, Map::kInstanceSizeOffset)); |
| 2516 } |
| 2517 |
| 2518 |
| 2499 void LCodeGen::DoCmpT(LCmpT* instr) { | 2519 void LCodeGen::DoCmpT(LCmpT* instr) { |
| 2500 Token::Value op = instr->op(); | 2520 Token::Value op = instr->op(); |
| 2501 | 2521 |
| 2502 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2522 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 2503 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2523 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2504 // On MIPS there is no need for a "no inlined smi code" marker (nop). | 2524 // On MIPS there is no need for a "no inlined smi code" marker (nop). |
| 2505 | 2525 |
| 2506 Condition condition = ComputeCompareCondition(op); | 2526 Condition condition = ComputeCompareCondition(op); |
| 2507 // A minor optimization that relies on LoadRoot always emitting one | 2527 // A minor optimization that relies on LoadRoot always emitting one |
| 2508 // instruction. | 2528 // instruction. |
| (...skipping 2759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5268 : LDeferredCode(codegen), instr_(instr) { } | 5288 : LDeferredCode(codegen), instr_(instr) { } |
| 5269 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } | 5289 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } |
| 5270 virtual LInstruction* instr() { return instr_; } | 5290 virtual LInstruction* instr() { return instr_; } |
| 5271 private: | 5291 private: |
| 5272 LAllocate* instr_; | 5292 LAllocate* instr_; |
| 5273 }; | 5293 }; |
| 5274 | 5294 |
| 5275 DeferredAllocate* deferred = | 5295 DeferredAllocate* deferred = |
| 5276 new(zone()) DeferredAllocate(this, instr); | 5296 new(zone()) DeferredAllocate(this, instr); |
| 5277 | 5297 |
| 5278 Register size = ToRegister(instr->size()); | |
| 5279 Register result = ToRegister(instr->result()); | 5298 Register result = ToRegister(instr->result()); |
| 5280 Register scratch = ToRegister(instr->temp1()); | 5299 Register scratch = ToRegister(instr->temp1()); |
| 5281 Register scratch2 = ToRegister(instr->temp2()); | 5300 Register scratch2 = ToRegister(instr->temp2()); |
| 5282 | 5301 |
| 5283 HAllocate* original_instr = instr->hydrogen(); | 5302 // Allocate memory for the object. |
| 5284 if (original_instr->size()->IsConstant()) { | 5303 AllocationFlags flags = TAG_OBJECT; |
| 5285 UNREACHABLE(); | 5304 if (instr->hydrogen()->MustAllocateDoubleAligned()) { |
| 5286 } else { | 5305 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); |
| 5287 // Allocate memory for the object. | 5306 } |
| 5288 AllocationFlags flags = TAG_OBJECT; | 5307 if (instr->size()->IsConstantOperand()) { |
| 5289 if (original_instr->MustAllocateDoubleAligned()) { | 5308 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| 5290 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); | |
| 5291 } | |
| 5292 __ AllocateInNewSpace(size, | 5309 __ AllocateInNewSpace(size, |
| 5293 result, | 5310 result, |
| 5294 scratch, | 5311 scratch, |
| 5295 scratch2, | 5312 scratch2, |
| 5296 deferred->entry(), | 5313 deferred->entry(), |
| 5297 TAG_OBJECT); | 5314 flags); |
| 5315 } else { |
| 5316 Register size = ToRegister(instr->size()); |
| 5317 __ AllocateInNewSpace(size, |
| 5318 result, |
| 5319 scratch, |
| 5320 scratch2, |
| 5321 deferred->entry(), |
| 5322 flags); |
| 5298 } | 5323 } |
| 5299 | 5324 |
| 5300 __ bind(deferred->exit()); | 5325 __ bind(deferred->exit()); |
| 5301 } | 5326 } |
| 5302 | 5327 |
| 5303 | 5328 |
| 5304 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { | 5329 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { |
| 5305 Register size = ToRegister(instr->size()); | 5330 Register size = ToRegister(instr->size()); |
| 5306 Register result = ToRegister(instr->result()); | 5331 Register result = ToRegister(instr->result()); |
| 5307 | 5332 |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5538 } | 5563 } |
| 5539 | 5564 |
| 5540 | 5565 |
| 5541 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { | 5566 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { |
| 5542 ASSERT(ToRegister(instr->result()).is(v0)); | 5567 ASSERT(ToRegister(instr->result()).is(v0)); |
| 5543 Handle<FixedArray> literals(instr->environment()->closure()->literals()); | 5568 Handle<FixedArray> literals(instr->environment()->closure()->literals()); |
| 5544 Handle<FixedArray> constant_properties = | 5569 Handle<FixedArray> constant_properties = |
| 5545 instr->hydrogen()->constant_properties(); | 5570 instr->hydrogen()->constant_properties(); |
| 5546 | 5571 |
| 5547 // Set up the parameters to the stub/runtime call. | 5572 // Set up the parameters to the stub/runtime call. |
| 5548 __ LoadHeapObject(t0, literals); | 5573 __ LoadHeapObject(a3, literals); |
| 5549 __ li(a3, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); | 5574 __ li(a2, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| 5550 __ li(a2, Operand(constant_properties)); | 5575 __ li(a1, Operand(constant_properties)); |
| 5551 int flags = instr->hydrogen()->fast_elements() | 5576 int flags = instr->hydrogen()->fast_elements() |
| 5552 ? ObjectLiteral::kFastElements | 5577 ? ObjectLiteral::kFastElements |
| 5553 : ObjectLiteral::kNoFlags; | 5578 : ObjectLiteral::kNoFlags; |
| 5554 __ li(a1, Operand(Smi::FromInt(flags))); | 5579 __ li(a0, Operand(Smi::FromInt(flags))); |
| 5555 __ Push(t0, a3, a2, a1); | |
| 5556 | 5580 |
| 5557 // Pick the right runtime function or stub to call. | 5581 // Pick the right runtime function or stub to call. |
| 5558 int properties_count = constant_properties->length() / 2; | 5582 int properties_count = constant_properties->length() / 2; |
| 5559 if (instr->hydrogen()->depth() > 1) { | 5583 if (instr->hydrogen()->depth() > 1) { |
| 5584 __ Push(a3, a2, a1, a0); |
| 5560 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); | 5585 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); |
| 5561 } else if (flags != ObjectLiteral::kFastElements || | 5586 } else if (flags != ObjectLiteral::kFastElements || |
| 5562 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 5587 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
| 5588 __ Push(a3, a2, a1, a0); |
| 5563 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); | 5589 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); |
| 5564 } else { | 5590 } else { |
| 5565 FastCloneShallowObjectStub stub(properties_count); | 5591 FastCloneShallowObjectStub stub(properties_count); |
| 5566 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 5592 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 5567 } | 5593 } |
| 5568 } | 5594 } |
| 5569 | 5595 |
| 5570 | 5596 |
| 5571 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5597 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
| 5572 ASSERT(ToRegister(instr->value()).is(a0)); | 5598 ASSERT(ToRegister(instr->value()).is(a0)); |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6038 __ Subu(scratch, result, scratch); | 6064 __ Subu(scratch, result, scratch); |
| 6039 __ lw(result, FieldMemOperand(scratch, | 6065 __ lw(result, FieldMemOperand(scratch, |
| 6040 FixedArray::kHeaderSize - kPointerSize)); | 6066 FixedArray::kHeaderSize - kPointerSize)); |
| 6041 __ bind(&done); | 6067 __ bind(&done); |
| 6042 } | 6068 } |
| 6043 | 6069 |
| 6044 | 6070 |
| 6045 #undef __ | 6071 #undef __ |
| 6046 | 6072 |
| 6047 } } // namespace v8::internal | 6073 } } // namespace v8::internal |
| OLD | NEW |