Commit eee34dd5 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

Introduce "optimized_out" oddball marker for compilers.

This introduces {optimized_out} as another Oddball kind to be used by
optimizing compilers when values are being optimized away. The aim is
providing visibility when this value leaks into the application domain.
Currently this will lead to {undefined} values appearing which then
silently propagate through the application. The special oddball can be
identified easily as a bug and also the debugger can treat it specially
when needed.

R=jarin@chromium.org

Review URL: https://codereview.chromium.org/1810483002

Cr-Commit-Position: refs/heads/master@{#34817}
parent 5d62db74
......@@ -646,7 +646,7 @@ void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
}
NonLiveFrameStateSlotReplacer replacer(
&state_values_cache_, jsgraph()->UndefinedConstant(),
&state_values_cache_, jsgraph()->OptimizedOutConstant(),
liveness_analyzer()->local_count(), local_zone());
Variable* arguments = info()->scope()->arguments();
if (arguments != nullptr && arguments->IsStackAllocated()) {
......
......@@ -29,6 +29,10 @@ Node* JSGraph::EmptyFixedArrayConstant() {
HeapConstant(factory()->empty_fixed_array()));
}
Node* JSGraph::OptimizedOutConstant() {
return CACHED(kOptimizedOutConstant,
HeapConstant(factory()->optimized_out()));
}
Node* JSGraph::UndefinedConstant() {
return CACHED(kUndefinedConstant, HeapConstant(factory()->undefined_value()));
......
......@@ -41,6 +41,7 @@ class JSGraph : public ZoneObject {
// Canonicalized global constants.
Node* CEntryStubConstant(int result_size);
Node* EmptyFixedArrayConstant();
Node* OptimizedOutConstant();
Node* UndefinedConstant();
Node* TheHoleConstant();
Node* TrueConstant();
......@@ -136,6 +137,7 @@ class JSGraph : public ZoneObject {
enum CachedNode {
kCEntryStubConstant,
kEmptyFixedArrayConstant,
kOptimizedOutConstant,
kUndefinedConstant,
kTheHoleConstant,
kTrueConstant,
......
......@@ -37,9 +37,9 @@ void HEnvironmentLivenessAnalysisPhase::ZapEnvironmentSlot(
int index, HSimulate* simulate) {
int operand_index = simulate->ToOperandIndex(index);
if (operand_index == -1) {
simulate->AddAssignedValue(index, graph()->GetConstantUndefined());
simulate->AddAssignedValue(index, graph()->GetConstantOptimizedOut());
} else {
simulate->SetOperandAt(operand_index, graph()->GetConstantUndefined());
simulate->SetOperandAt(operand_index, graph()->GetConstantOptimizedOut());
}
}
......
......@@ -690,28 +690,32 @@ HConstant* HGraph::GetConstantBool(bool value) {
return value ? GetConstantTrue() : GetConstantFalse();
}
#define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value, \
undetectable) \
HConstant* HGraph::GetConstant##Name() { \
if (!constant_##name##_.is_set()) { \
HConstant* constant = new (zone()) HConstant( \
Unique<Object>::CreateImmovable( \
isolate()->factory()->name##_value()), \
Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()), \
false, Representation::Tagged(), htype, true, boolean_value, \
undetectable, ODDBALL_TYPE); \
constant->InsertAfter(entry_block()->first()); \
constant_##name##_.set(constant); \
} \
return ReinsertConstantIfNecessary(constant_##name##_.get()); \
}
DEFINE_GET_CONSTANT(Undefined, undefined, undefined, HType::Undefined(), false,
true)
DEFINE_GET_CONSTANT(True, true, boolean, HType::Boolean(), true, false)
DEFINE_GET_CONSTANT(False, false, boolean, HType::Boolean(), false, false)
DEFINE_GET_CONSTANT(Hole, the_hole, the_hole, HType::None(), false, false)
DEFINE_GET_CONSTANT(Null, null, null, HType::Null(), false, true)
#define DEFINE_GET_CONSTANT(Name, name, constant, type, htype, boolean_value, \
undetectable) \
HConstant* HGraph::GetConstant##Name() { \
if (!constant_##name##_.is_set()) { \
HConstant* constant = new (zone()) HConstant( \
Unique<Object>::CreateImmovable(isolate()->factory()->constant()), \
Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()), \
false, Representation::Tagged(), htype, true, boolean_value, \
undetectable, ODDBALL_TYPE); \
constant->InsertAfter(entry_block()->first()); \
constant_##name##_.set(constant); \
} \
return ReinsertConstantIfNecessary(constant_##name##_.get()); \
}
DEFINE_GET_CONSTANT(Undefined, undefined, undefined_value, undefined,
HType::Undefined(), false, true)
DEFINE_GET_CONSTANT(True, true, true_value, boolean, HType::Boolean(), true,
false)
DEFINE_GET_CONSTANT(False, false, false_value, boolean, HType::Boolean(), false,
false)
DEFINE_GET_CONSTANT(Hole, the_hole, the_hole_value, the_hole, HType::None(),
false, false)
DEFINE_GET_CONSTANT(Null, null, null_value, null, HType::Null(), false, true)
DEFINE_GET_CONSTANT(OptimizedOut, optimized_out, optimized_out, optimized_out,
HType::None(), false, false)
#undef DEFINE_GET_CONSTANT
......
......@@ -334,6 +334,7 @@ class HGraph final : public ZoneObject {
HConstant* GetConstantBool(bool value);
HConstant* GetConstantHole();
HConstant* GetConstantNull();
HConstant* GetConstantOptimizedOut();
HConstant* GetInvalidContext();
bool IsConstantUndefined(HConstant* constant);
......@@ -472,6 +473,7 @@ class HGraph final : public ZoneObject {
SetOncePointer<HConstant> constant_false_;
SetOncePointer<HConstant> constant_the_hole_;
SetOncePointer<HConstant> constant_null_;
SetOncePointer<HConstant> constant_optimized_out_;
SetOncePointer<HConstant> constant_invalid_context_;
HOsrBuilder* osr_;
......
......@@ -133,8 +133,10 @@ void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
if (scope_info->LocalIsSynthetic(i)) continue;
Handle<String> name(scope_info->StackLocalName(i));
Handle<Object> value = GetExpression(scope_info->StackLocalIndex(i));
// TODO(yangguo): We convert optimized out values to {undefined} when they
// are passed to the debugger. Eventually we should handle them somehow.
if (value->IsTheHole()) value = isolate_->factory()->undefined_value();
if (value->IsOptimizedOut()) value = isolate_->factory()->undefined_value();
JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
}
}
......
......@@ -2329,6 +2329,7 @@ bool Heap::CreateInitialMaps() {
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, no_interceptor_result_sentinel);
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, exception);
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, termination_exception);
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, optimized_out);
for (unsigned i = 0; i < arraysize(string_type_table); i++) {
const StringTypeTable& entry = string_type_table[i];
......@@ -2700,6 +2701,11 @@ void Heap::CreateInitialObjects() {
handle(Smi::FromInt(-5), isolate()), false,
"undefined", Oddball::kException));
set_optimized_out(
*factory->NewOddball(factory->optimized_out_map(), "optimized_out",
handle(Smi::FromInt(-6), isolate()), false,
"undefined", Oddball::kOptimizedOut));
for (unsigned i = 0; i < arraysize(constant_string_table); i++) {
Handle<String> str =
factory->InternalizeUtf8String(constant_string_table[i].contents);
......
......@@ -75,6 +75,7 @@ namespace internal {
V(Oddball, arguments_marker, ArgumentsMarker) \
V(Oddball, exception, Exception) \
V(Oddball, termination_exception, TerminationException) \
V(Oddball, optimized_out, OptimizedOut) \
V(FixedArray, number_string_cache, NumberStringCache) \
V(Object, instanceof_cache_function, InstanceofCacheFunction) \
V(Object, instanceof_cache_map, InstanceofCacheMap) \
......@@ -147,6 +148,7 @@ namespace internal {
V(Map, no_interceptor_result_sentinel_map, NoInterceptorResultSentinelMap) \
V(Map, exception_map, ExceptionMap) \
V(Map, termination_exception_map, TerminationExceptionMap) \
V(Map, optimized_out_map, OptimizedOutMap) \
V(Map, message_object_map, JSMessageObjectMap) \
V(Map, foreign_map, ForeignMap) \
V(Map, neander_map, NeanderMap) \
......
......@@ -619,7 +619,7 @@ void Oddball::OddballVerify() {
CHECK(number->IsSmi());
int value = Smi::cast(number)->value();
// Hidden oddballs have negative smis.
const int kLeastHiddenOddballNumber = -5;
const int kLeastHiddenOddballNumber = -6;
CHECK_LE(value, 1);
CHECK(value >= kLeastHiddenOddballNumber);
}
......@@ -642,6 +642,8 @@ void Oddball::OddballVerify() {
CHECK(this == heap->termination_exception());
} else if (map() == heap->exception_map()) {
CHECK(this == heap->exception());
} else if (map() == heap->optimized_out_map()) {
CHECK(this == heap->optimized_out());
} else {
UNREACHABLE();
}
......
......@@ -1004,7 +1004,8 @@ template <class C> inline bool Is(Object* obj);
V(Uninitialized) \
V(True) \
V(False) \
V(ArgumentsMarker)
V(ArgumentsMarker) \
V(OptimizedOut)
// The element types selection for CreateListFromArrayLike.
enum class ElementTypes { kAll, kStringAndSymbol };
......@@ -9595,6 +9596,7 @@ class Oddball: public HeapObject {
static const byte kUninitialized = 6;
static const byte kOther = 7;
static const byte kException = 8;
static const byte kOptimizedOut = 9;
typedef FixedBodyDescriptor<kToStringOffset, kTypeOfOffset + kPointerSize,
kSize> BodyDescriptor;
......
......@@ -554,7 +554,11 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
// Use the value from the stack.
if (scope_info->LocalIsSynthetic(i)) continue;
locals->set(local * 2, scope_info->LocalName(i));
locals->set(local * 2 + 1, *(frame_inspector.GetExpression(i)));
Handle<Object> value = frame_inspector.GetExpression(i);
// TODO(yangguo): We convert optimized out values to {undefined} when they
// are passed to the debugger. Eventually we should handle them somehow.
if (value->IsOptimizedOut()) value = isolate->factory()->undefined_value();
locals->set(local * 2 + 1, *value);
local++;
}
if (local < local_count) {
......
......@@ -191,7 +191,8 @@ Type::bitset BitsetType::Lub(i::Map* map) {
map == heap->uninitialized_map() ||
map == heap->no_interceptor_result_sentinel_map() ||
map == heap->termination_exception_map() ||
map == heap->arguments_marker_map());
map == heap->arguments_marker_map() ||
map == heap->optimized_out_map());
return kInternal & kTaggedPointer;
}
case HEAP_NUMBER_TYPE:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment