[deoptimizer] Preserve double bit patterns correctly.

This makes sure that the deoptimizer preserves the exact bit pattern of
floating-point values (both 32-bit and 64-bit) up to the point where a
potential {HeapNumber} is allocated. It in turn allows us to correctly
recognize the {hole_nan_value} when stored into a {FixedDouleArray}.

R=jarin@chromium.org
TEST=mjsunit/regress/regress-crbug-684208
BUG=chromium:684208

Review-Url: https://codereview.chromium.org/2652303002
Cr-Commit-Position: refs/heads/master@{#42679}
This commit is contained in:
mstarzinger 2017-01-26 01:25:59 -08:00 committed by Commit bot
parent f6d0dc6d88
commit 7376e12e00
12 changed files with 113 additions and 42 deletions

View File

@ -95,7 +95,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; ++i) {
double double_value = input_->GetDoubleRegister(i);
Float64 double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
}

View File

@ -78,7 +78,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
for (int i = 0; i < DoubleRegister::kMaxNumRegisters; ++i) {
double double_value = input_->GetDoubleRegister(i);
Float64 double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
}

View File

@ -2793,7 +2793,7 @@ TranslatedValue TranslatedValue::NewDuplicateObject(TranslatedState* container,
// static
TranslatedValue TranslatedValue::NewFloat(TranslatedState* container,
float value) {
Float32 value) {
TranslatedValue slot(container, kFloat);
slot.float_value_ = value;
return slot;
@ -2801,7 +2801,7 @@ TranslatedValue TranslatedValue::NewFloat(TranslatedState* container,
// static
TranslatedValue TranslatedValue::NewDouble(TranslatedState* container,
double value) {
Float64 value) {
TranslatedValue slot(container, kDouble);
slot.double_value_ = value;
return slot;
@ -2870,12 +2870,12 @@ uint32_t TranslatedValue::uint32_value() const {
return uint32_value_;
}
float TranslatedValue::float_value() const {
Float32 TranslatedValue::float_value() const {
DCHECK_EQ(kFloat, kind());
return float_value_;
}
double TranslatedValue::double_value() const {
Float64 TranslatedValue::double_value() const {
DCHECK_EQ(kDouble, kind());
return double_value_;
}
@ -2985,22 +2985,29 @@ void TranslatedValue::MaterializeSimple() {
}
switch (kind()) {
case kInt32: {
case kInt32:
value_ = Handle<Object>(isolate()->factory()->NewNumber(int32_value()));
return;
}
case kUInt32:
value_ = Handle<Object>(isolate()->factory()->NewNumber(uint32_value()));
return;
case kFloat:
value_ = Handle<Object>(isolate()->factory()->NewNumber(float_value()));
case kFloat: {
double scalar_value = float_value().get_scalar();
value_ = Handle<Object>(isolate()->factory()->NewNumber(scalar_value));
return;
}
case kDouble:
value_ = Handle<Object>(isolate()->factory()->NewNumber(double_value()));
case kDouble: {
if (double_value().is_hole_nan()) {
value_ = isolate()->factory()->hole_nan_value();
return;
}
double scalar_value = double_value().get_scalar();
value_ = Handle<Object>(isolate()->factory()->NewNumber(scalar_value));
return;
}
case kCapturedObject:
case kDuplicatedObject:
@ -3048,6 +3055,13 @@ uint32_t TranslatedState::GetUInt32Slot(Address fp, int slot_offset) {
#endif
}
Float32 TranslatedState::GetFloatSlot(Address fp, int slot_offset) {
return Float32::FromBits(GetUInt32Slot(fp, slot_offset));
}
Float64 TranslatedState::GetDoubleSlot(Address fp, int slot_offset) {
return Float64::FromBits(Memory::uint64_at(fp + slot_offset));
}
void TranslatedValue::Handlify() {
if (kind() == kTagged) {
@ -3403,9 +3417,9 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
case Translation::FLOAT_REGISTER: {
int input_reg = iterator->Next();
if (registers == nullptr) return TranslatedValue::NewInvalid(this);
float value = registers->GetFloatRegister(input_reg);
Float32 value = registers->GetFloatRegister(input_reg);
if (trace_file != nullptr) {
PrintF(trace_file, "%e ; %s (float)", value,
PrintF(trace_file, "%e ; %s (float)", value.get_scalar(),
RegisterConfiguration::Crankshaft()->GetFloatRegisterName(
input_reg));
}
@ -3415,9 +3429,9 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
case Translation::DOUBLE_REGISTER: {
int input_reg = iterator->Next();
if (registers == nullptr) return TranslatedValue::NewInvalid(this);
double value = registers->GetDoubleRegister(input_reg);
Float64 value = registers->GetDoubleRegister(input_reg);
if (trace_file != nullptr) {
PrintF(trace_file, "%e ; %s (double)", value,
PrintF(trace_file, "%e ; %s (double)", value.get_scalar(),
RegisterConfiguration::Crankshaft()->GetDoubleRegisterName(
input_reg));
}
@ -3473,9 +3487,9 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
case Translation::FLOAT_STACK_SLOT: {
int slot_offset =
OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
float value = ReadFloatValue(fp + slot_offset);
Float32 value = GetFloatSlot(fp, slot_offset);
if (trace_file != nullptr) {
PrintF(trace_file, "%e ; (float) [fp %c %d] ", value,
PrintF(trace_file, "%e ; (float) [fp %c %d] ", value.get_scalar(),
slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
}
return TranslatedValue::NewFloat(this, value);
@ -3484,9 +3498,9 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
case Translation::DOUBLE_STACK_SLOT: {
int slot_offset =
OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
double value = ReadDoubleValue(fp + slot_offset);
Float64 value = GetDoubleSlot(fp, slot_offset);
if (trace_file != nullptr) {
PrintF(trace_file, "%e ; (double) [fp %c %d] ", value,
PrintF(trace_file, "%e ; (double) [fp %c %d] ", value.get_scalar(),
slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
}
return TranslatedValue::NewDouble(this, value);
@ -3857,7 +3871,11 @@ Handle<Object> TranslatedState::MaterializeCapturedObjectAt(
for (int i = 0; i < length; ++i) {
Handle<Object> value = materializer.FieldAt(value_index);
CHECK(value->IsNumber());
double_array->set(i, value->Number());
if (value.is_identical_to(isolate_->factory()->hole_nan_value())) {
double_array->set_the_hole(isolate_, i);
} else {
double_array->set(i, value->Number());
}
}
}
return object;

View File

@ -20,6 +20,37 @@ class DeoptimizedFrameInfo;
class TranslatedState;
class RegisterValues;
// Safety wrapper for a 32-bit floating-point value to make sure we don't loose
// the exact bit pattern during deoptimization when passing this value. Note
// that there is intentionally no way to construct it from a {float} value.
class Float32 {
public:
Float32() : bit_pattern_(0) {}
uint32_t get_bits() const { return bit_pattern_; }
float get_scalar() const { return bit_cast<float>(bit_pattern_); }
static Float32 FromBits(uint32_t bits) { return Float32(bits); }
private:
explicit Float32(uint32_t bit_pattern) : bit_pattern_(bit_pattern) {}
uint32_t bit_pattern_;
};
// Safety wrapper for a 64-bit floating-point value to make sure we don't loose
// the exact bit pattern during deoptimization when passing this value. Note
// that there is intentionally no way to construct it from a {double} value.
class Float64 {
public:
Float64() : bit_pattern_(0) {}
uint64_t get_bits() const { return bit_pattern_; }
double get_scalar() const { return bit_cast<double>(bit_pattern_); }
bool is_hole_nan() const { return bit_pattern_ == kHoleNanInt64; }
static Float64 FromBits(uint64_t bits) { return Float64(bits); }
private:
explicit Float64(uint64_t bit_pattern) : bit_pattern_(bit_pattern) {}
uint64_t bit_pattern_;
};
class TranslatedValue {
public:
// Allocation-less getter of the value.
@ -64,8 +95,8 @@ class TranslatedValue {
static TranslatedValue NewDeferredObject(TranslatedState* container,
int length, int object_index);
static TranslatedValue NewDuplicateObject(TranslatedState* container, int id);
static TranslatedValue NewFloat(TranslatedState* container, float value);
static TranslatedValue NewDouble(TranslatedState* container, double value);
static TranslatedValue NewFloat(TranslatedState* container, Float32 value);
static TranslatedValue NewDouble(TranslatedState* container, Float64 value);
static TranslatedValue NewInt32(TranslatedState* container, int32_t value);
static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value);
static TranslatedValue NewBool(TranslatedState* container, uint32_t value);
@ -98,9 +129,9 @@ class TranslatedValue {
// kind is kInt32.
int32_t int32_value_;
// kind is kFloat
float float_value_;
Float32 float_value_;
// kind is kDouble
double double_value_;
Float64 double_value_;
// kind is kDuplicatedObject or kArgumentsObject or kCapturedObject.
MaterializedObjectInfo materialization_info_;
};
@ -109,8 +140,8 @@ class TranslatedValue {
Object* raw_literal() const;
int32_t int32_value() const;
uint32_t uint32_value() const;
float float_value() const;
double double_value() const;
Float32 float_value() const;
Float64 double_value() const;
int object_length() const;
int object_index() const;
};
@ -298,6 +329,8 @@ class TranslatedState {
bool GetAdaptedArguments(Handle<JSObject>* result, int frame_index);
static uint32_t GetUInt32Slot(Address fp, int slot_index);
static Float32 GetFloatSlot(Address fp, int slot_index);
static Float64 GetDoubleSlot(Address fp, int slot_index);
std::vector<TranslatedFrame> frames_;
Isolate* isolate_;
@ -652,12 +685,12 @@ class RegisterValues {
return registers_[n];
}
float GetFloatRegister(unsigned n) const {
Float32 GetFloatRegister(unsigned n) const {
DCHECK(n < arraysize(float_registers_));
return float_registers_[n];
}
double GetDoubleRegister(unsigned n) const {
Float64 GetDoubleRegister(unsigned n) const {
DCHECK(n < arraysize(double_registers_));
return double_registers_[n];
}
@ -667,19 +700,24 @@ class RegisterValues {
registers_[n] = value;
}
void SetFloatRegister(unsigned n, float value) {
void SetFloatRegister(unsigned n, Float32 value) {
DCHECK(n < arraysize(float_registers_));
float_registers_[n] = value;
}
void SetDoubleRegister(unsigned n, double value) {
void SetDoubleRegister(unsigned n, Float64 value) {
DCHECK(n < arraysize(double_registers_));
double_registers_[n] = value;
}
// Generated code is writing directly into the below arrays, make sure their
// element sizes fit what the machine instructions expect.
static_assert(sizeof(Float32) == kFloatSize, "size mismatch");
static_assert(sizeof(Float64) == kDoubleSize, "size mismatch");
intptr_t registers_[Register::kNumRegisters];
float float_registers_[FloatRegister::kMaxNumRegisters];
double double_registers_[DoubleRegister::kMaxNumRegisters];
Float32 float_registers_[FloatRegister::kMaxNumRegisters];
Float64 double_registers_[DoubleRegister::kMaxNumRegisters];
};
@ -732,7 +770,7 @@ class FrameDescription {
return register_values_.GetRegister(n);
}
double GetDoubleRegister(unsigned n) const {
Float64 GetDoubleRegister(unsigned n) const {
return register_values_.GetDoubleRegister(n);
}
@ -740,7 +778,7 @@ class FrameDescription {
register_values_.SetRegister(n, value);
}
void SetDoubleRegister(unsigned n, double value) {
void SetDoubleRegister(unsigned n, Float64 value) {
register_values_.SetDoubleRegister(n, value);
}

View File

@ -181,7 +181,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
for (int i = 0; i < XMMRegister::kMaxNumRegisters; ++i) {
double double_value = input_->GetDoubleRegister(i);
Float64 double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
}

View File

@ -93,7 +93,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
for (int i = 0; i < DoubleRegister::kMaxNumRegisters; ++i) {
double double_value = input_->GetDoubleRegister(i);
Float64 double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
}

View File

@ -93,7 +93,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
for (int i = 0; i < DoubleRegister::kMaxNumRegisters; ++i) {
double double_value = input_->GetDoubleRegister(i);
Float64 double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
}

View File

@ -101,7 +101,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
for (int i = 0; i < DoubleRegister::kNumRegisters; ++i) {
double double_value = input_->GetDoubleRegister(i);
Float64 double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
}

View File

@ -95,7 +95,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
for (int i = 0; i < DoubleRegister::kNumRegisters; ++i) {
double double_value = input_->GetDoubleRegister(i);
Float64 double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
}

View File

@ -100,7 +100,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
for (int i = 0; i < XMMRegister::kMaxNumRegisters; ++i) {
double double_value = input_->GetDoubleRegister(i);
Float64 double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
}

View File

@ -181,7 +181,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
for (int i = 0; i < X87Register::kMaxNumRegisters; ++i) {
double double_value = input_->GetDoubleRegister(i);
Float64 double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
}

View File

@ -0,0 +1,15 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
function foo() {
var a = [1, 2.3, /*hole*/, 4.2];
%_DeoptimizeNow();
return a[2];
}
assertSame(undefined, foo());
assertSame(undefined, foo());
%OptimizeFunctionOnNextCall(foo)
assertSame(undefined, foo());