| Index: src/x64/lithium-codegen-x64.cc
|
| diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
|
| index c6bb097b50fc04d6e79f9b26cf7c5c633f095815..7825f891a328e5ba375cbb8d39fd115e38809b30 100644
|
| --- a/src/x64/lithium-codegen-x64.cc
|
| +++ b/src/x64/lithium-codegen-x64.cc
|
| @@ -39,7 +39,7 @@ namespace internal {
|
|
|
| // When invoking builtins, we need to record the safepoint in the middle of
|
| // the invoke instruction sequence generated by the macro assembler.
|
| -class SafepointGenerator : public PostCallGenerator {
|
| +class SafepointGenerator : public CallWrapper {
|
| public:
|
| SafepointGenerator(LCodeGen* codegen,
|
| LPointerMap* pointers,
|
| @@ -48,29 +48,29 @@ class SafepointGenerator : public PostCallGenerator {
|
| : codegen_(codegen),
|
| pointers_(pointers),
|
| deoptimization_index_(deoptimization_index),
|
| - ensure_reloc_space_(ensure_reloc_space),
|
| - previous_safepoint_position_(-kMinSafepointSize) { }
|
| + ensure_reloc_space_(ensure_reloc_space) { }
|
| virtual ~SafepointGenerator() { }
|
|
|
| - virtual void Generate() {
|
| + virtual void BeforeCall(int call_size) {
|
| + ASSERT(call_size >= 0);
|
| // Ensure that we have enough space after the previous safepoint position
|
| - // for the generated code there.
|
| - int position = codegen_->masm()->pc_offset();
|
| - ASSERT(position > previous_safepoint_position_);
|
| - if (position < previous_safepoint_position_ + kMinSafepointSize) {
|
| - int padding_size =
|
| - previous_safepoint_position_ + kMinSafepointSize - position;
|
| + // for the jump generated there.
|
| + int call_end = codegen_->masm()->pc_offset() + call_size;
|
| + int prev_jump_end = codegen_->LastSafepointEnd() + kMinSafepointSize;
|
| + if (call_end < prev_jump_end) {
|
| + int padding_size = prev_jump_end - call_end;
|
| STATIC_ASSERT(kMinSafepointSize <= 9); // One multibyte nop is enough.
|
| codegen_->masm()->nop(padding_size);
|
| - position += padding_size;
|
| }
|
| + }
|
| +
|
| + virtual void AfterCall() {
|
| // Ensure that we have enough space in the reloc info to patch
|
| // this with calls when doing deoptimization.
|
| if (ensure_reloc_space_) {
|
| codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true);
|
| }
|
| codegen_->RecordSafepoint(pointers_, deoptimization_index_);
|
| - previous_safepoint_position_ = position;
|
| }
|
|
|
| private:
|
| @@ -80,7 +80,6 @@ class SafepointGenerator : public PostCallGenerator {
|
| LPointerMap* pointers_;
|
| int deoptimization_index_;
|
| bool ensure_reloc_space_;
|
| - int previous_safepoint_position_;
|
| };
|
|
|
|
|
| @@ -259,9 +258,8 @@ LInstruction* LCodeGen::GetNextInstruction() {
|
|
|
| bool LCodeGen::GenerateJumpTable() {
|
| for (int i = 0; i < jump_table_.length(); i++) {
|
| - JumpTableEntry* info = jump_table_[i];
|
| - __ bind(&(info->label_));
|
| - __ Jump(info->address_, RelocInfo::RUNTIME_ENTRY);
|
| + __ bind(&jump_table_[i].label);
|
| + __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY);
|
| }
|
| return !is_aborted();
|
| }
|
| @@ -539,17 +537,13 @@ void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) {
|
| if (cc == no_condition) {
|
| __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
|
| } else {
|
| - JumpTableEntry* jump_info = NULL;
|
| // We often have several deopts to the same entry, reuse the last
|
| // jump entry if this is the case.
|
| - if (jump_table_.length() > 0 &&
|
| - jump_table_[jump_table_.length() - 1]->address_ == entry) {
|
| - jump_info = jump_table_[jump_table_.length() - 1];
|
| - } else {
|
| - jump_info = new JumpTableEntry(entry);
|
| - jump_table_.Add(jump_info);
|
| + if (jump_table_.is_empty() ||
|
| + jump_table_.last().address != entry) {
|
| + jump_table_.Add(entry);
|
| }
|
| - __ j(cc, &jump_info->label_);
|
| + __ j(cc, &jump_table_.last().label);
|
| }
|
| }
|
|
|
| @@ -725,11 +719,6 @@ void LCodeGen::DoCallStub(LCallStub* instr) {
|
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| break;
|
| }
|
| - case CodeStub::MathPow: {
|
| - MathPowStub stub;
|
| - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| - break;
|
| - }
|
| case CodeStub::NumberToString: {
|
| NumberToStringStub stub;
|
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| @@ -1067,10 +1056,10 @@ void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
|
| }
|
|
|
|
|
| -void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) {
|
| +void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
|
| Register result = ToRegister(instr->result());
|
| Register array = ToRegister(instr->InputAt(0));
|
| - __ movq(result, FieldOperand(array, PixelArray::kLengthOffset));
|
| + __ movq(result, FieldOperand(array, ExternalPixelArray::kLengthOffset));
|
| }
|
|
|
|
|
| @@ -1834,24 +1823,50 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
| LInstanceOfKnownGlobal* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| virtual void Generate() {
|
| - codegen()->DoDeferredLInstanceOfKnownGlobal(instr_);
|
| + codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_);
|
| }
|
|
|
| + Label* map_check() { return &map_check_; }
|
| +
|
| private:
|
| LInstanceOfKnownGlobal* instr_;
|
| + Label map_check_;
|
| };
|
|
|
|
|
| DeferredInstanceOfKnownGlobal* deferred;
|
| deferred = new DeferredInstanceOfKnownGlobal(this, instr);
|
|
|
| - Label false_result;
|
| + Label done, false_result;
|
| Register object = ToRegister(instr->InputAt(0));
|
|
|
| // A Smi is not an instance of anything.
|
| __ JumpIfSmi(object, &false_result);
|
|
|
| - // Null is not an instance of anything.
|
| + // This is the inlined call site instanceof cache. The two occurences of the
|
| + // hole value will be patched to the last map/result pair generated by the
|
| + // instanceof stub.
|
| + NearLabel cache_miss;
|
| + // Use a temp register to avoid memory operands with variable lengths.
|
| + Register map = ToRegister(instr->TempAt(0));
|
| + __ movq(map, FieldOperand(object, HeapObject::kMapOffset));
|
| + __ bind(deferred->map_check()); // Label for calculating code patching.
|
| + __ Move(kScratchRegister, Factory::the_hole_value());
|
| + __ cmpq(map, kScratchRegister); // Patched to cached map.
|
| + __ j(not_equal, &cache_miss);
|
| + // Patched to load either true or false.
|
| + __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
|
| +#ifdef DEBUG
|
| + // Check that the code size between patch label and patch sites is invariant.
|
| + Label end_of_patched_code;
|
| + __ bind(&end_of_patched_code);
|
| + ASSERT(true);
|
| +#endif
|
| + __ jmp(&done);
|
| +
|
| + // The inlined call site cache did not match. Check for null and string
|
| + // before calling the deferred code.
|
| + __ bind(&cache_miss); // Null is not an instance of anything.
|
| __ CompareRoot(object, Heap::kNullValueRootIndex);
|
| __ j(equal, &false_result);
|
|
|
| @@ -1862,17 +1877,26 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
| __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
|
|
|
| __ bind(deferred->exit());
|
| + __ bind(&done);
|
| }
|
|
|
|
|
| -void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
| +void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
| + Label* map_check) {
|
| __ PushSafepointRegisters();
|
| -
|
| - InstanceofStub stub(InstanceofStub::kNoFlags);
|
| + InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>(
|
| + InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck);
|
| + InstanceofStub stub(flags);
|
|
|
| __ push(ToRegister(instr->InputAt(0)));
|
| __ Push(instr->function());
|
| - __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + Register temp = ToRegister(instr->TempAt(0));
|
| + ASSERT(temp.is(rdi));
|
| + static const int kAdditionalDelta = 16;
|
| + int delta =
|
| + masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
|
| + __ movq(temp, Immediate(delta));
|
| + __ push(temp);
|
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| __ movq(kScratchRegister, rax);
|
| __ PopSafepointRegisters();
|
| @@ -2072,7 +2096,7 @@ void LCodeGen::DoLoadElements(LLoadElements* instr) {
|
| FACTORY->fixed_array_map());
|
| __ j(equal, &done);
|
| __ Cmp(FieldOperand(result, HeapObject::kMapOffset),
|
| - FACTORY->pixel_array_map());
|
| + FACTORY->external_pixel_array_map());
|
| __ j(equal, &done);
|
| __ Cmp(FieldOperand(result, HeapObject::kMapOffset),
|
| FACTORY->fixed_cow_array_map());
|
| @@ -2082,11 +2106,12 @@ void LCodeGen::DoLoadElements(LLoadElements* instr) {
|
| }
|
|
|
|
|
| -void LCodeGen::DoLoadPixelArrayExternalPointer(
|
| - LLoadPixelArrayExternalPointer* instr) {
|
| +void LCodeGen::DoLoadExternalArrayPointer(
|
| + LLoadExternalArrayPointer* instr) {
|
| Register result = ToRegister(instr->result());
|
| Register input = ToRegister(instr->InputAt(0));
|
| - __ movq(result, FieldOperand(input, PixelArray::kExternalPointerOffset));
|
| + __ movq(result, FieldOperand(input,
|
| + ExternalPixelArray::kExternalPointerOffset));
|
| }
|
|
|
|
|
| @@ -2574,6 +2599,8 @@ void LCodeGen::DoPower(LPower* instr) {
|
| }
|
| // Return value is in xmm0.
|
| __ movsd(result_reg, xmm0);
|
| + // Restore context register.
|
| + __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| }
|
|
|
|
|
|
|