From aaddea11b225fd9b004f5cb6e572c1d74c23fcfb Mon Sep 17 00:00:00 2001 From: jarin Date: Thu, 23 Apr 2015 01:07:12 -0700 Subject: [PATCH] Materialize booleans in the turbofan deoptimizer. BUG= R=titzer@chromium.org Review URL: https://codereview.chromium.org/1055453006 Cr-Commit-Position: refs/heads/master@{#28022} --- src/compiler/code-generator.cc | 14 ++--- src/deoptimizer.cc | 140 ++++++++++++++++++++++++++++++++++++++++- src/deoptimizer.h | 43 +++++++------ src/objects.cc | 13 ++++ test/mjsunit/mjsunit.status | 4 -- 5 files changed, 182 insertions(+), 32 deletions(-) diff --git a/src/compiler/code-generator.cc b/src/compiler/code-generator.cc index 114190c..dd6565c 100644 --- a/src/compiler/code-generator.cc +++ b/src/compiler/code-generator.cc @@ -528,10 +528,9 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation, InstructionOperand* op, MachineType type) { if (op->IsStackSlot()) { - // TODO(jarin) kMachBool and kRepBit should materialize true and false - // rather than creating an int value. - if (type == kMachBool || type == kRepBit || type == kMachInt32 || - type == kMachInt8 || type == kMachInt16) { + if (type == kMachBool || type == kRepBit) { + translation->StoreBoolStackSlot(StackSlotOperand::cast(op)->index()); + } else if (type == kMachInt32 || type == kMachInt8 || type == kMachInt16) { translation->StoreInt32StackSlot(StackSlotOperand::cast(op)->index()); } else if (type == kMachUint32 || type == kMachUint16 || type == kMachUint8) { @@ -547,10 +546,9 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation, DoubleStackSlotOperand::cast(op)->index()); } else if (op->IsRegister()) { InstructionOperandConverter converter(this, instr); - // TODO(jarin) kMachBool and kRepBit should materialize true and false - // rather than creating an int value. - if (type == kMachBool || type == kRepBit || type == kMachInt32 || - type == kMachInt8 || type == kMachInt16) { + if (type == kMachBool || type == kRepBit) { + translation->StoreBoolRegister(converter.ToRegister(op)); + } else if (type == kMachInt32 || type == kMachInt8 || type == kMachInt16) { translation->StoreInt32Register(converter.ToRegister(op)); } else if (type == kMachUint32 || type == kMachUint16 || type == kMachUint8) { diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc index eaedb2c..1f32f1c 100644 --- a/src/deoptimizer.cc +++ b/src/deoptimizer.cc @@ -829,14 +829,17 @@ void Deoptimizer::DoComputeOutputFrames() { case Translation::REGISTER: case Translation::INT32_REGISTER: case Translation::UINT32_REGISTER: + case Translation::BOOL_REGISTER: case Translation::DOUBLE_REGISTER: case Translation::STACK_SLOT: case Translation::INT32_STACK_SLOT: case Translation::UINT32_STACK_SLOT: + case Translation::BOOL_STACK_SLOT: case Translation::DOUBLE_STACK_SLOT: case Translation::LITERAL: case Translation::ARGUMENTS_OBJECT: - default: + case Translation::DUPLICATED_OBJECT: + case Translation::CAPTURED_OBJECT: FATAL("Unsupported translation"); break; } @@ -2101,10 +2104,12 @@ void Deoptimizer::DoTranslateObjectAndSkip(TranslationIterator* iterator) { case Translation::REGISTER: case Translation::INT32_REGISTER: case Translation::UINT32_REGISTER: + case Translation::BOOL_REGISTER: case Translation::DOUBLE_REGISTER: case Translation::STACK_SLOT: case Translation::INT32_STACK_SLOT: case Translation::UINT32_STACK_SLOT: + case Translation::BOOL_STACK_SLOT: case Translation::DOUBLE_STACK_SLOT: case Translation::LITERAL: { // The value is not part of any materialized object, so we can ignore it. @@ -2237,6 +2242,28 @@ void Deoptimizer::DoTranslateObject(TranslationIterator* iterator, return; } + case Translation::BOOL_REGISTER: { + int input_reg = iterator->Next(); + uintptr_t value = static_cast(input_->GetRegister(input_reg)); + bool is_smi = (value <= static_cast(Smi::kMaxValue)); + if (trace_scope_ != NULL) { + PrintF(trace_scope_->file(), + " object @0x%08" V8PRIxPTR ": [field #%d] <- ", + reinterpret_cast(object_slot), field_index); + PrintF(trace_scope_->file(), "%" V8PRIuPTR " ; bool %s (%s)\n", value, + converter.NameOfCPURegister(input_reg), TraceValueType(is_smi)); + } + if (value == 0) { + AddObjectTaggedValue( + reinterpret_cast(isolate_->heap()->false_value())); + } else { + DCHECK_EQ(1, value); + AddObjectTaggedValue( + reinterpret_cast(isolate_->heap()->true_value())); + } + return; + } + case Translation::DOUBLE_REGISTER: { int input_reg = iterator->Next(); double value = input_->GetDoubleRegister(input_reg); @@ -2323,6 +2350,30 @@ void Deoptimizer::DoTranslateObject(TranslationIterator* iterator, return; } + case Translation::BOOL_STACK_SLOT: { + int input_slot_index = iterator->Next(); + unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index); + uintptr_t value = + static_cast(input_->GetFrameSlot(input_offset)); + bool is_smi = (value <= static_cast(Smi::kMaxValue)); + if (trace_scope_ != NULL) { + PrintF(trace_scope_->file(), + " object @0x%08" V8PRIxPTR ": [field #%d] <- ", + reinterpret_cast(object_slot), field_index); + PrintF(trace_scope_->file(), "%" V8PRIuPTR " ; [sp + %d] (bool %s)\n", + value, input_offset, TraceValueType(is_smi)); + } + if (value == 0) { + AddObjectTaggedValue( + reinterpret_cast(isolate_->heap()->false_value())); + } else { + DCHECK_EQ(1, value); + AddObjectTaggedValue( + reinterpret_cast(isolate_->heap()->true_value())); + } + return; + } + case Translation::DOUBLE_STACK_SLOT: { int input_slot_index = iterator->Next(); unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index); @@ -2505,6 +2556,31 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, return; } + case Translation::BOOL_REGISTER: { + int input_reg = iterator->Next(); + uintptr_t value = static_cast(input_->GetRegister(input_reg)); + bool is_smi = value <= static_cast(Smi::kMaxValue); + if (trace_scope_ != NULL) { + PrintF(trace_scope_->file(), + " 0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIuPTR + " ; bool %s (%s)\n", + output_[frame_index]->GetTop() + output_offset, output_offset, + value, converter.NameOfCPURegister(input_reg), + TraceValueType(is_smi)); + } + if (value == 0) { + output_[frame_index]->SetFrameSlot( + output_offset, + reinterpret_cast(isolate_->heap()->false_value())); + } else { + DCHECK_EQ(1, value); + output_[frame_index]->SetFrameSlot( + output_offset, + reinterpret_cast(isolate_->heap()->true_value())); + } + return; + } + case Translation::DOUBLE_REGISTER: { int input_reg = iterator->Next(); double value = input_->GetDoubleRegister(input_reg); @@ -2605,6 +2681,32 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, return; } + case Translation::BOOL_STACK_SLOT: { + int input_slot_index = iterator->Next(); + unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index); + uintptr_t value = + static_cast(input_->GetFrameSlot(input_offset)); + bool is_smi = value <= static_cast(Smi::kMaxValue); + if (trace_scope_ != NULL) { + PrintF(trace_scope_->file(), " 0x%08" V8PRIxPTR ": ", + output_[frame_index]->GetTop() + output_offset); + PrintF(trace_scope_->file(), + "[top + %d] <- %" V8PRIuPTR " ; [sp + %d] (uint32 %s)\n", + output_offset, value, input_offset, TraceValueType(is_smi)); + } + if (value == 0) { + output_[frame_index]->SetFrameSlot( + output_offset, + reinterpret_cast(isolate_->heap()->false_value())); + } else { + DCHECK_EQ(1, value); + output_[frame_index]->SetFrameSlot( + output_offset, + reinterpret_cast(isolate_->heap()->true_value())); + } + return; + } + case Translation::DOUBLE_STACK_SLOT: { int input_slot_index = iterator->Next(); unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index); @@ -3020,6 +3122,12 @@ void Translation::StoreUint32Register(Register reg) { } +void Translation::StoreBoolRegister(Register reg) { + buffer_->Add(BOOL_REGISTER, zone()); + buffer_->Add(reg.code(), zone()); +} + + void Translation::StoreDoubleRegister(DoubleRegister reg) { buffer_->Add(DOUBLE_REGISTER, zone()); buffer_->Add(DoubleRegister::ToAllocationIndex(reg), zone()); @@ -3044,6 +3152,12 @@ void Translation::StoreUint32StackSlot(int index) { } +void Translation::StoreBoolStackSlot(int index) { + buffer_->Add(BOOL_STACK_SLOT, zone()); + buffer_->Add(index, zone()); +} + + void Translation::StoreDoubleStackSlot(int index) { buffer_->Add(DOUBLE_STACK_SLOT, zone()); buffer_->Add(index, zone()); @@ -3076,10 +3190,12 @@ int Translation::NumberOfOperandsFor(Opcode opcode) { case REGISTER: case INT32_REGISTER: case UINT32_REGISTER: + case BOOL_REGISTER: case DOUBLE_REGISTER: case STACK_SLOT: case INT32_STACK_SLOT: case UINT32_STACK_SLOT: + case BOOL_STACK_SLOT: case DOUBLE_STACK_SLOT: case LITERAL: case COMPILED_STUB_FRAME: @@ -3143,6 +3259,7 @@ SlotRef SlotRefValueBuilder::ComputeSlotForNextArgument( case Translation::REGISTER: case Translation::INT32_REGISTER: case Translation::UINT32_REGISTER: + case Translation::BOOL_REGISTER: case Translation::DOUBLE_REGISTER: // We are at safepoint which corresponds to call. All registers are // saved by caller so there would be no live registers at this @@ -3167,6 +3284,12 @@ SlotRef SlotRefValueBuilder::ComputeSlotForNextArgument( return SlotRef(slot_addr, SlotRef::UINT32); } + case Translation::BOOL_STACK_SLOT: { + int slot_index = iterator->Next(); + Address slot_addr = SlotAddress(frame, slot_index); + return SlotRef(slot_addr, SlotRef::BOOLBIT); + } + case Translation::DOUBLE_STACK_SLOT: { int slot_index = iterator->Next(); Address slot_addr = SlotAddress(frame, slot_index); @@ -3324,6 +3447,20 @@ Handle SlotRef::GetValue(Isolate* isolate) { } } + case BOOLBIT: { +#if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT + uint32_t value = Memory::uint32_at(addr_ + kIntSize); +#else + uint32_t value = Memory::uint32_at(addr_); +#endif + if (value == 0) { + return isolate->factory()->false_value(); + } else { + DCHECK_EQ(1, value); + return isolate->factory()->true_value(); + } + } + case DOUBLE: { double value = read_double_value(addr_); return isolate->factory()->NewNumber(value); @@ -3396,6 +3533,7 @@ Handle SlotRefValueBuilder::GetNext(Isolate* isolate, int lvl) { case SlotRef::TAGGED: case SlotRef::INT32: case SlotRef::UINT32: + case SlotRef::BOOLBIT: case SlotRef::DOUBLE: case SlotRef::LITERAL: return slot.GetValue(isolate); diff --git a/src/deoptimizer.h b/src/deoptimizer.h index 25e96f2..9ad20d9 100644 --- a/src/deoptimizer.h +++ b/src/deoptimizer.h @@ -755,25 +755,27 @@ class TranslationIterator BASE_EMBEDDED { }; -#define TRANSLATION_OPCODE_LIST(V) \ - V(BEGIN) \ - V(JS_FRAME) \ - V(CONSTRUCT_STUB_FRAME) \ - V(GETTER_STUB_FRAME) \ - V(SETTER_STUB_FRAME) \ - V(ARGUMENTS_ADAPTOR_FRAME) \ - V(COMPILED_STUB_FRAME) \ - V(DUPLICATED_OBJECT) \ - V(ARGUMENTS_OBJECT) \ - V(CAPTURED_OBJECT) \ - V(REGISTER) \ - V(INT32_REGISTER) \ - V(UINT32_REGISTER) \ - V(DOUBLE_REGISTER) \ - V(STACK_SLOT) \ - V(INT32_STACK_SLOT) \ - V(UINT32_STACK_SLOT) \ - V(DOUBLE_STACK_SLOT) \ +#define TRANSLATION_OPCODE_LIST(V) \ + V(BEGIN) \ + V(JS_FRAME) \ + V(CONSTRUCT_STUB_FRAME) \ + V(GETTER_STUB_FRAME) \ + V(SETTER_STUB_FRAME) \ + V(ARGUMENTS_ADAPTOR_FRAME) \ + V(COMPILED_STUB_FRAME) \ + V(DUPLICATED_OBJECT) \ + V(ARGUMENTS_OBJECT) \ + V(CAPTURED_OBJECT) \ + V(REGISTER) \ + V(INT32_REGISTER) \ + V(UINT32_REGISTER) \ + V(BOOL_REGISTER) \ + V(DOUBLE_REGISTER) \ + V(STACK_SLOT) \ + V(INT32_STACK_SLOT) \ + V(UINT32_STACK_SLOT) \ + V(BOOL_STACK_SLOT) \ + V(DOUBLE_STACK_SLOT) \ V(LITERAL) @@ -811,10 +813,12 @@ class Translation BASE_EMBEDDED { void StoreRegister(Register reg); void StoreInt32Register(Register reg); void StoreUint32Register(Register reg); + void StoreBoolRegister(Register reg); void StoreDoubleRegister(DoubleRegister reg); void StoreStackSlot(int index); void StoreInt32StackSlot(int index); void StoreUint32StackSlot(int index); + void StoreBoolStackSlot(int index); void StoreDoubleStackSlot(int index); void StoreLiteral(int literal_id); void StoreArgumentsObject(bool args_known, int args_index, int args_length); @@ -844,6 +848,7 @@ class SlotRef BASE_EMBEDDED { TAGGED, INT32, UINT32, + BOOLBIT, DOUBLE, LITERAL, DEFERRED_OBJECT, // Object captured by the escape analysis. diff --git a/src/objects.cc b/src/objects.cc index fa158fa..6880a01 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -11616,6 +11616,13 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint( break; } + case Translation::BOOL_REGISTER: { + int reg_code = iterator.Next(); + os << "{input=" << converter.NameOfCPURegister(reg_code) + << " (bool)}"; + break; + } + case Translation::DOUBLE_REGISTER: { int reg_code = iterator.Next(); os << "{input=" << DoubleRegister::AllocationIndexToString(reg_code) @@ -11641,6 +11648,12 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint( break; } + case Translation::BOOL_STACK_SLOT: { + int input_slot_index = iterator.Next(); + os << "{input=" << input_slot_index << " (bool)}"; + break; + } + case Translation::DOUBLE_STACK_SLOT: { int input_slot_index = iterator.Next(); os << "{input=" << input_slot_index << "}"; diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status index 432cbc0..0e8b01b 100644 --- a/test/mjsunit/mjsunit.status +++ b/test/mjsunit/mjsunit.status @@ -62,10 +62,6 @@ # from the deoptimizer to do that. 'arguments-indirect': [PASS, NO_VARIANTS], - # TODO(jarin): deoptimizer materializes a number instead of a boolean. - 'compiler/deopt-bool': [PASS, NO_VARIANTS], - 'compiler/deopt-bool2': [PASS, NO_VARIANTS], - # TODO(verwaest): Some tests are over-restrictive about object layout. 'array-constructor-feedback': [PASS, NO_VARIANTS], 'array-feedback': [PASS, NO_VARIANTS], -- 2.7.4