summaryrefslogtreecommitdiff
path: root/chromium/v8/src/hydrogen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/hydrogen.cc')
-rw-r--r--chromium/v8/src/hydrogen.cc501
1 files changed, 222 insertions, 279 deletions
diff --git a/chromium/v8/src/hydrogen.cc b/chromium/v8/src/hydrogen.cc
index ba1de7aa225..aab64d64d45 100644
--- a/chromium/v8/src/hydrogen.cc
+++ b/chromium/v8/src/hydrogen.cc
@@ -834,14 +834,14 @@ void HGraphBuilder::IfBuilder::Else() {
}
-void HGraphBuilder::IfBuilder::Deopt(const char* reason) {
+void HGraphBuilder::IfBuilder::Deopt() {
ASSERT(did_then_);
if (did_else_) {
deopt_else_ = true;
} else {
deopt_then_ = true;
}
- builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
+ builder_->Add<HDeoptimize>(Deoptimizer::EAGER);
}
@@ -966,9 +966,8 @@ void HGraphBuilder::LoopBuilder::EndBody() {
// Push the new increment value on the expression stack to merge into the phi.
builder_->environment()->Push(increment_);
- HBasicBlock* last_block = builder_->current_block();
- last_block->GotoNoSimulate(header_block_);
- header_block_->loop_information()->RegisterBackEdge(last_block);
+ builder_->current_block()->GotoNoSimulate(header_block_);
+ header_block_->loop_information()->RegisterBackEdge(body_block_);
builder_->set_current_block(exit_block_);
// Pop the phi from the expression stack
@@ -1043,9 +1042,9 @@ HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
void HGraphBuilder::FinishExitWithHardDeoptimization(
- const char* reason, HBasicBlock* continuation) {
+ HBasicBlock* continuation) {
PadEnvironmentForContinuation(current_block(), continuation);
- Add<HDeoptimize>(reason, Deoptimizer::EAGER);
+ Add<HDeoptimize>(Deoptimizer::EAGER);
if (graph()->IsInsideNoSideEffectsScope()) {
current_block()->GotoNoSimulate(continuation);
} else {
@@ -1059,14 +1058,12 @@ void HGraphBuilder::PadEnvironmentForContinuation(
HBasicBlock* continuation) {
if (continuation->last_environment() != NULL) {
// When merging from a deopt block to a continuation, resolve differences in
- // environment by pushing constant 0 and popping extra values so that the
- // environments match during the join. Push 0 since it has the most specific
- // representation, and will not influence representation inference of the
- // phi.
+ // environment by pushing undefined and popping extra values so that the
+ // environments match during the join.
int continuation_env_length = continuation->last_environment()->length();
while (continuation_env_length != from->last_environment()->length()) {
if (continuation_env_length > from->last_environment()->length()) {
- from->last_environment()->Push(graph()->GetConstant0());
+ from->last_environment()->Push(graph()->GetConstantUndefined());
} else {
from->last_environment()->Pop();
}
@@ -1117,7 +1114,7 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
IfBuilder key_checker(this);
key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT);
key_checker.Then();
- key_checker.ElseDeopt("Key out of capacity range");
+ key_checker.ElseDeopt();
key_checker.End();
HValue* new_capacity = BuildNewElementsCapacity(key);
@@ -1273,7 +1270,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
negative_checker.Then();
HInstruction* result = AddExternalArrayElementAccess(
external_elements, key, val, bounds_check, elements_kind, is_store);
- negative_checker.ElseDeopt("Negative key encountered");
+ negative_checker.ElseDeopt();
length_checker.End();
return result;
} else {
@@ -1635,26 +1632,13 @@ void HGraphBuilder::BuildCopyElements(HValue* from_elements,
from_elements_kind,
ALLOW_RETURN_HOLE);
- ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
- IsFastSmiElementsKind(to_elements_kind))
+ ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind)
? FAST_HOLEY_ELEMENTS : to_elements_kind;
-
- if (IsHoleyElementsKind(from_elements_kind) &&
- from_elements_kind != to_elements_kind) {
- IfBuilder if_hole(this);
- if_hole.If<HCompareHoleAndBranch>(element);
- if_hole.Then();
- HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
- ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double())
- : graph()->GetConstantHole();
- Add<HStoreKeyed>(to_elements, key, hole_constant, kind);
- if_hole.Else();
- HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
- store->SetFlag(HValue::kAllowUndefinedAsNaN);
- if_hole.End();
- } else {
- HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
- store->SetFlag(HValue::kAllowUndefinedAsNaN);
+ HInstruction* holey_store = Add<HStoreKeyed>(to_elements, key,
+ element, holey_kind);
+ // Allow NaN hole values to converted to their tagged counterparts.
+ if (IsFastHoleyElementsKind(to_elements_kind)) {
+ holey_store->SetFlag(HValue::kAllowUndefinedAsNaN);
}
builder.EndBody();
@@ -1741,6 +1725,38 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate,
}
+HInstruction* HGraphBuilder::BuildUnaryMathOp(
+ HValue* input, Handle<Type> type, Token::Value operation) {
+ // We only handle the numeric cases here
+ type = handle(
+ Type::Intersect(type, handle(Type::Number(), isolate())), isolate());
+
+ switch (operation) {
+ default:
+ UNREACHABLE();
+ case Token::SUB: {
+ HInstruction* instr =
+ NewUncasted<HMul>(input, graph()->GetConstantMinus1());
+ Representation rep = Representation::FromType(type);
+ if (type->Is(Type::None())) {
+ Add<HDeoptimize>(Deoptimizer::SOFT);
+ }
+ if (instr->IsBinaryOperation()) {
+ HBinaryOperation* binop = HBinaryOperation::cast(instr);
+ binop->set_observed_input_representation(1, rep);
+ binop->set_observed_input_representation(2, rep);
+ }
+ return instr;
+ }
+ case Token::BIT_NOT:
+ if (type->Is(Type::None())) {
+ Add<HDeoptimize>(Deoptimizer::SOFT);
+ }
+ return New<HBitNot>(input);
+ }
+}
+
+
void HGraphBuilder::BuildCompareNil(
HValue* value,
Handle<Type> type,
@@ -1773,7 +1789,7 @@ void HGraphBuilder::BuildCompareNil(
// emitted below is the actual monomorphic map.
BuildCheckMap(value, type->Classes().Current());
} else {
- if_nil.Deopt("Too many undetectable types");
+ if_nil.Deopt();
}
}
@@ -2572,7 +2588,7 @@ void ValueContext::ReturnValue(HValue* value) {
// The value is tracked in the bailout environment, and communicated
// through the environment as the result of the expression.
if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) {
- owner()->Bailout(kBadValueContextForArgumentsValue);
+ owner()->Bailout("bad value context for arguments value");
}
owner()->Push(value);
}
@@ -2624,7 +2640,7 @@ void EffectContext::ReturnContinuation(HIfContinuation* continuation,
void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
ASSERT(!instr->IsControlInstruction());
if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
- return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
+ return owner()->Bailout("bad value context for arguments object value");
}
owner()->AddInstruction(instr);
owner()->Push(instr);
@@ -2637,7 +2653,7 @@ void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
ASSERT(!instr->HasObservableSideEffects());
if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
- return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
+ return owner()->Bailout("bad value context for arguments object value");
}
HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
@@ -2727,7 +2743,7 @@ void TestContext::BuildBranch(HValue* value) {
// branch.
HOptimizedGraphBuilder* builder = owner();
if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
- builder->Bailout(kArgumentsObjectValueInATestContext);
+ builder->Bailout("arguments object value in a test context");
}
if (value->IsConstant()) {
HConstant* constant_value = HConstant::cast(value);
@@ -2773,7 +2789,7 @@ void TestContext::BuildBranch(HValue* value) {
} while (false)
-void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
+void HOptimizedGraphBuilder::Bailout(const char* reason) {
current_info()->set_bailout_reason(reason);
SetStackOverflow();
}
@@ -2832,16 +2848,16 @@ void HOptimizedGraphBuilder::VisitExpressions(
bool HOptimizedGraphBuilder::BuildGraph() {
if (current_info()->function()->is_generator()) {
- Bailout(kFunctionIsAGenerator);
+ Bailout("function is a generator");
return false;
}
Scope* scope = current_info()->scope();
if (scope->HasIllegalRedeclaration()) {
- Bailout(kFunctionWithIllegalRedeclaration);
+ Bailout("function with illegal redeclaration");
return false;
}
if (scope->calls_eval()) {
- Bailout(kFunctionCallsEval);
+ Bailout("function calls eval");
return false;
}
SetUpScope(scope);
@@ -2907,7 +2923,8 @@ bool HOptimizedGraphBuilder::BuildGraph() {
}
-bool HGraph::Optimize(BailoutReason* bailout_reason) {
+bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
+ *bailout_reason = SmartArrayPointer<char>();
OrderBlocks();
AssignDominators();
@@ -2928,20 +2945,19 @@ bool HGraph::Optimize(BailoutReason* bailout_reason) {
Run<HPropagateDeoptimizingMarkPhase>();
if (!CheckConstPhiUses()) {
- *bailout_reason = kUnsupportedPhiUseOfConstVariable;
+ *bailout_reason = SmartArrayPointer<char>(StrDup(
+ "Unsupported phi use of const variable"));
return false;
}
Run<HRedundantPhiEliminationPhase>();
if (!CheckArgumentsPhiUses()) {
- *bailout_reason = kUnsupportedPhiUseOfArguments;
+ *bailout_reason = SmartArrayPointer<char>(StrDup(
+ "Unsupported phi use of arguments"));
return false;
}
// Remove dead code and phis
if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
-
- if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
-
CollectPhis();
if (has_osr()) osr()->FinishOsrValues();
@@ -2965,20 +2981,22 @@ bool HGraph::Optimize(BailoutReason* bailout_reason) {
if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
+ if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
+
if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
if (FLAG_use_range) Run<HRangeAnalysisPhase>();
- Run<HComputeChangeUndefinedToNaN>();
Run<HComputeMinusZeroChecksPhase>();
// Eliminate redundant stack checks on backwards branches.
Run<HStackCheckEliminationPhase>();
- if (FLAG_array_bounds_checks_elimination) {
+ if (FLAG_idefs) SetupInformativeDefinitions();
+ if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) {
Run<HBoundsCheckEliminationPhase>();
}
- if (FLAG_array_bounds_checks_hoisting) {
+ if (FLAG_array_bounds_checks_hoisting && !FLAG_idefs) {
Run<HBoundsCheckHoistingPhase>();
}
if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
@@ -2990,6 +3008,50 @@ bool HGraph::Optimize(BailoutReason* bailout_reason) {
}
+void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) {
+ for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) {
+ HPhi* phi = block->phis()->at(phi_index);
+ phi->AddInformativeDefinitions();
+ phi->SetFlag(HValue::kIDefsProcessingDone);
+ // We do not support phis that "redefine just one operand".
+ ASSERT(!phi->IsInformativeDefinition());
+ }
+
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* i = it.Current();
+ i->AddInformativeDefinitions();
+ i->SetFlag(HValue::kIDefsProcessingDone);
+ i->UpdateRedefinedUsesWhileSettingUpInformativeDefinitions();
+ }
+}
+
+
+// This method is recursive, so if its stack frame is large it could
+// cause a stack overflow.
+// To keep the individual stack frames small we do the actual work inside
+// SetupInformativeDefinitionsInBlock();
+void HGraph::SetupInformativeDefinitionsRecursively(HBasicBlock* block) {
+ SetupInformativeDefinitionsInBlock(block);
+ for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
+ SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i));
+ }
+
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* i = it.Current();
+ if (i->IsBoundsCheck()) {
+ HBoundsCheck* check = HBoundsCheck::cast(i);
+ check->ApplyIndexChange();
+ }
+ }
+}
+
+
+void HGraph::SetupInformativeDefinitions() {
+ HPhase phase("H_Setup informative definitions", this);
+ SetupInformativeDefinitionsRecursively(entry_block());
+}
+
+
void HGraph::RestoreActualValues() {
HPhase phase("H_Restore actual values", this);
@@ -3072,7 +3134,7 @@ void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
// not have declarations).
if (scope->arguments() != NULL) {
if (!scope->arguments()->IsStackAllocated()) {
- return Bailout(kContextAllocatedArguments);
+ return Bailout("context-allocated arguments");
}
environment()->Bind(scope->arguments(),
@@ -3093,7 +3155,7 @@ void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
if (stmt->scope() != NULL) {
- return Bailout(kScopedBlock);
+ return Bailout("ScopedBlock");
}
BreakAndContinueInfo break_info(stmt);
{ BreakAndContinueScope push(&break_info, this);
@@ -3305,7 +3367,7 @@ void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kWithStatement);
+ return Bailout("WithStatement");
}
@@ -3320,12 +3382,12 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
ZoneList<CaseClause*>* clauses = stmt->cases();
int clause_count = clauses->length();
if (clause_count > kCaseClauseLimit) {
- return Bailout(kSwitchStatementTooManyClauses);
+ return Bailout("SwitchStatement: too many clauses");
}
ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH);
if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) {
- return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels);
+ return Bailout("SwitchStatement: mixed or non-literal switch labels");
}
HValue* context = environment()->context();
@@ -3371,7 +3433,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
if (!clause->compare_type()->Is(Type::Smi())) {
- Add<HDeoptimize>("Non-smi switch type", Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
}
HCompareNumericAndBranch* compare_ =
@@ -3617,16 +3679,16 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
ASSERT(current_block()->HasPredecessor());
if (!FLAG_optimize_for_in) {
- return Bailout(kForInStatementOptimizationIsDisabled);
+ return Bailout("ForInStatement optimization is disabled");
}
if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) {
- return Bailout(kForInStatementIsNotFastCase);
+ return Bailout("ForInStatement is not fast case");
}
if (!stmt->each()->IsVariableProxy() ||
!stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
- return Bailout(kForInStatementWithNonLocalEachVariable);
+ return Bailout("ForInStatement with non-local each variable");
}
Variable* each_var = stmt->each()->AsVariableProxy()->var();
@@ -3720,7 +3782,7 @@ void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kForOfStatement);
+ return Bailout("ForOfStatement");
}
@@ -3728,7 +3790,7 @@ void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kTryCatchStatement);
+ return Bailout("TryCatchStatement");
}
@@ -3737,7 +3799,7 @@ void HOptimizedGraphBuilder::VisitTryFinallyStatement(
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kTryFinallyStatement);
+ return Bailout("TryFinallyStatement");
}
@@ -3745,7 +3807,7 @@ void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kDebuggerStatement);
+ return Bailout("DebuggerStatement");
}
@@ -3791,7 +3853,7 @@ void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral(
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kSharedFunctionInfoLiteral);
+ return Bailout("SharedFunctionInfoLiteral");
}
@@ -3871,7 +3933,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
case Variable::UNALLOCATED: {
if (IsLexicalVariableMode(variable->mode())) {
// TODO(rossberg): should this be an ASSERT?
- return Bailout(kReferenceToGlobalLexicalVariable);
+ return Bailout("reference to global lexical variable");
}
// Handle known global constants like 'undefined' specially to avoid a
// load from a global cell for them.
@@ -3928,7 +3990,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
if (value == graph()->GetConstantHole()) {
ASSERT(IsDeclaredVariableMode(variable->mode()) &&
variable->mode() != VAR);
- return Bailout(kReferenceToUninitializedVariable);
+ return Bailout("reference to uninitialized variable");
}
return ast_context()->ReturnValue(value);
}
@@ -3940,7 +4002,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
}
case Variable::LOOKUP:
- return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
+ return Bailout("reference to a variable which requires dynamic lookup");
}
}
@@ -4061,7 +4123,8 @@ static bool IsFastLiteral(Handle<JSObject> boilerplate,
int* data_size,
int* pointer_size) {
if (boilerplate->map()->is_deprecated()) {
- Handle<Object> result = JSObject::TryMigrateInstance(boilerplate);
+ Handle<Object> result =
+ JSObject::TryMigrateInstance(boilerplate);
if (result->IsSmi()) return false;
}
@@ -4238,7 +4301,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::PROTOTYPE:
case ObjectLiteral::Property::SETTER:
case ObjectLiteral::Property::GETTER:
- return Bailout(kObjectLiteralWithComplexProperty);
+ return Bailout("Object literal with complex property");
default: UNREACHABLE();
}
}
@@ -4277,7 +4340,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate(
isolate(), literals, expr->constant_elements());
if (raw_boilerplate.is_null()) {
- return Bailout(kArrayBoilerplateCreationFailed);
+ return Bailout("array boilerplate creation failed");
}
site = isolate()->factory()->NewAllocationSite();
@@ -4369,7 +4432,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
CHECK_ALIVE(VisitForValue(subexpr));
HValue* value = Pop();
- if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
+ if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal");
elements = AddLoadElements(literal, type_check);
@@ -4450,7 +4513,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
if (proto_result.IsProperty()) {
// If the inherited property could induce readonly-ness, bail out.
if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) {
- Bailout(kImproperObjectOnPrototypeChainForStore);
+ Bailout("improper object on prototype chain for store");
return NULL;
}
// We only need to check up to the preexisting property.
@@ -4463,9 +4526,9 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
ASSERT(proto->GetPrototype(isolate())->IsNull());
}
ASSERT(proto->IsJSObject());
- BuildCheckPrototypeMaps(
+ Add<HCheckPrototypeMaps>(
Handle<JSObject>(JSObject::cast(map->prototype())),
- Handle<JSObject>(JSObject::cast(proto)));
+ Handle<JSObject>(JSObject::cast(proto)), top_info());
}
HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
@@ -4503,8 +4566,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
if (transition_to_field) {
Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
- HConstant* transition_constant = Add<HConstant>(transition);
- instr->SetTransition(transition_constant, top_info());
+ instr->SetTransition(transition, top_info());
// TODO(fschneider): Record the new map type of the object in the IR to
// enable elimination of redundant checks after the transition store.
instr->SetGVNFlag(kChangesMaps);
@@ -4620,43 +4682,14 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
- BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder);
+ Add<HCheckPrototypeMaps>(
+ Handle<JSObject>::cast(prototype), holder, top_info());
HValue* holder_value = Add<HConstant>(holder);
return BuildLoadNamedField(holder_value,
HObjectAccess::ForField(holder_map, &lookup, name), type_check);
}
-// Returns true if an instance of this map can never find a property with this
-// name in its prototype chain. This means all prototypes up to the top are
-// fast and don't have the name in them. It would be good if we could optimize
-// polymorphic loads where the property is sometimes found in the prototype
-// chain.
-static bool PrototypeChainCanNeverResolve(
- Handle<Map> map, Handle<String> name) {
- Isolate* isolate = map->GetIsolate();
- Object* current = map->prototype();
- while (current != isolate->heap()->null_value()) {
- if (current->IsJSGlobalProxy() ||
- current->IsGlobalObject() ||
- !current->IsJSObject() ||
- JSObject::cast(current)->map()->has_named_interceptor() ||
- JSObject::cast(current)->IsAccessCheckNeeded() ||
- !JSObject::cast(current)->HasFastProperties()) {
- return false;
- }
-
- LookupResult lookup(isolate);
- Map* map = JSObject::cast(current)->map();
- map->LookupDescriptor(NULL, *name, &lookup);
- if (lookup.IsFound()) return false;
- if (!lookup.IsCacheable()) return false;
- current = JSObject::cast(current)->GetPrototype();
- }
- return true;
-}
-
-
void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
Property* expr,
HValue* object,
@@ -4664,90 +4697,16 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
Handle<String> name) {
HInstruction* instr = TryLoadPolymorphicAsMonomorphic(
expr, object, types, name);
- if (instr != NULL) {
- instr->set_position(expr->position());
- return ast_context()->ReturnInstruction(instr, expr->id());
- }
-
- // Something did not match; must use a polymorphic load.
- int count = 0;
- HBasicBlock* join = NULL;
- for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
- Handle<Map> map = types->at(i);
- LookupResult lookup(isolate());
- if (ComputeLoadStoreField(map, name, &lookup, false) ||
- (lookup.IsCacheable() &&
- !map->is_dictionary_map() &&
- !map->has_named_interceptor() &&
- (lookup.IsConstant() ||
- (!lookup.IsFound() &&
- PrototypeChainCanNeverResolve(map, name))))) {
- if (count == 0) {
- BuildCheckHeapObject(object);
- join = graph()->CreateBasicBlock();
- }
- ++count;
- HBasicBlock* if_true = graph()->CreateBasicBlock();
- HBasicBlock* if_false = graph()->CreateBasicBlock();
- HCompareMap* compare =
- new(zone()) HCompareMap(object, map, if_true, if_false);
- current_block()->Finish(compare);
-
- set_current_block(if_true);
-
- // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic.
- if (lookup.IsField()) {
- HObjectAccess access = HObjectAccess::ForField(map, &lookup, name);
- HLoadNamedField* load = BuildLoadNamedField(object, access, compare);
- load->set_position(expr->position());
- AddInstruction(load);
- if (!ast_context()->IsEffect()) Push(load);
- } else if (lookup.IsConstant()) {
- Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
- HConstant* hconstant = Add<HConstant>(constant);
- if (!ast_context()->IsEffect()) Push(hconstant);
- } else {
- ASSERT(!lookup.IsFound());
- if (map->prototype()->IsJSObject()) {
- Handle<JSObject> prototype(JSObject::cast(map->prototype()));
- Handle<JSObject> holder = prototype;
- while (holder->map()->prototype()->IsJSObject()) {
- holder = handle(JSObject::cast(holder->map()->prototype()));
- }
- BuildCheckPrototypeMaps(prototype, holder);
- }
- if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
- }
-
- current_block()->Goto(join);
- set_current_block(if_false);
- }
- }
-
- // Finish up. Unconditionally deoptimize if we've handled all the maps we
- // know about and do not want to handle ones we've never seen. Otherwise
- // use a generic IC.
- if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
- FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
- } else {
- HInstruction* load = BuildLoadNamedGeneric(object, name, expr);
- load->set_position(expr->position());
- AddInstruction(load);
- if (!ast_context()->IsEffect()) Push(load);
-
- if (join != NULL) {
- current_block()->Goto(join);
- } else {
- Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
- if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
- return;
- }
+ if (instr == NULL) {
+ // Something did not match; must use a polymorphic load.
+ BuildCheckHeapObject(object);
+ HValue* context = environment()->context();
+ instr = new(zone()) HLoadNamedFieldPolymorphic(
+ context, object, types, name, zone());
}
- ASSERT(join != NULL);
- join->SetJoinId(expr->id());
- set_current_block(join);
- if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
+ instr->set_position(expr->position());
+ return ast_context()->ReturnInstruction(instr, expr->id());
}
@@ -4866,7 +4825,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
// know about and do not want to handle ones we've never seen. Otherwise
// use a generic IC.
if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
- FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join);
+ FinishExitWithHardDeoptimization(join);
} else {
HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value);
instr->set_position(position);
@@ -4914,10 +4873,7 @@ void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
HValue* value = environment()->ExpressionStackAt(0);
HValue* object = environment()->ExpressionStackAt(1);
- if (expr->IsUninitialized()) {
- Add<HDeoptimize>("Insufficient type feedback for property assignment",
- Deoptimizer::SOFT);
- }
+ if (expr->IsUninitialized()) Add<HDeoptimize>(Deoptimizer::SOFT);
return BuildStoreNamed(expr, expr->id(), expr->position(),
expr->AssignmentId(), prop, object, value, value);
} else {
@@ -4963,8 +4919,7 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
}
builder.Then();
builder.Else();
- Add<HDeoptimize>("Constant global variable assignment",
- Deoptimizer::EAGER);
+ Add<HDeoptimize>(Deoptimizer::EAGER);
builder.End();
}
HInstruction* instr =
@@ -5062,7 +5017,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
if (proxy != NULL) {
Variable* var = proxy->var();
if (var->mode() == LET) {
- return Bailout(kUnsupportedLetCompoundAssignment);
+ return Bailout("unsupported let compound assignment");
}
CHECK_ALIVE(VisitForValue(operation));
@@ -5078,7 +5033,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
case Variable::PARAMETER:
case Variable::LOCAL:
if (var->mode() == CONST) {
- return Bailout(kUnsupportedConstCompoundAssignment);
+ return Bailout("unsupported const compound assignment");
}
BindIfLive(var, Top());
break;
@@ -5094,7 +5049,8 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
int count = current_info()->scope()->num_parameters();
for (int i = 0; i < count; ++i) {
if (var == current_info()->scope()->parameter(i)) {
- Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
+ Bailout(
+ "assignment to parameter, function uses arguments object");
}
}
}
@@ -5125,7 +5081,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
}
case Variable::LOOKUP:
- return Bailout(kCompoundAssignmentToLookupSlot);
+ return Bailout("compound assignment to lookup slot");
}
return ast_context()->ReturnValue(Pop());
@@ -5173,7 +5129,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
}
- return BuildStoreNamed(expr, expr->id(), expr->position(),
+ return BuildStoreNamed(prop, expr->id(), expr->position(),
expr->AssignmentId(), prop, object, instr, instr);
} else {
// Keyed property.
@@ -5214,7 +5170,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
}
} else {
- return Bailout(kInvalidLhsInCompoundAssignment);
+ return Bailout("invalid lhs in compound assignment");
}
}
@@ -5251,11 +5207,11 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
}
} else if (var->mode() == CONST_HARMONY) {
if (expr->op() != Token::INIT_CONST_HARMONY) {
- return Bailout(kNonInitializerAssignmentToConst);
+ return Bailout("non-initializer assignment to const");
}
}
- if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
+ if (proxy->IsArguments()) return Bailout("assignment to arguments");
// Handle the assignment.
switch (var->location()) {
@@ -5274,7 +5230,7 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
if (var->mode() == LET && expr->op() == Token::ASSIGN) {
HValue* env_value = environment()->Lookup(var);
if (env_value == graph()->GetConstantHole()) {
- return Bailout(kAssignmentToLetVariableBeforeInitialization);
+ return Bailout("assignment to let variable before initialization");
}
}
// We do not allow the arguments object to occur in a context where it
@@ -5296,7 +5252,7 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
int count = current_info()->scope()->num_parameters();
for (int i = 0; i < count; ++i) {
if (var == current_info()->scope()->parameter(i)) {
- return Bailout(kAssignmentToParameterInArgumentsObject);
+ return Bailout("assignment to parameter in arguments object");
}
}
}
@@ -5337,10 +5293,10 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
}
case Variable::LOOKUP:
- return Bailout(kAssignmentToLOOKUPVariable);
+ return Bailout("assignment to LOOKUP variable");
}
} else {
- return Bailout(kInvalidLeftHandSideInAssignment);
+ return Bailout("invalid left-hand side in assignment");
}
}
@@ -5405,8 +5361,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
Handle<String> name,
Property* expr) {
if (expr->IsUninitialized()) {
- Add<HDeoptimize>("Insufficient feedback for generic named load",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
}
HValue* context = environment()->context();
return new(zone()) HLoadNamedGeneric(context, object, name);
@@ -5463,7 +5418,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
HCheckMaps* type_check = AddCheckMap(object, map);
- BuildCheckPrototypeMaps(prototype, holder);
+ Add<HCheckPrototypeMaps>(prototype, holder, top_info());
HValue* holder_value = Add<HConstant>(holder);
return BuildLoadNamedField(holder_value,
HObjectAccess::ForField(holder_map, &lookup, name), type_check);
@@ -5475,7 +5430,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
AddCheckMap(object, map);
- BuildCheckPrototypeMaps(prototype, holder);
+ Add<HCheckPrototypeMaps>(prototype, holder, top_info());
Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
return New<HConstant>(constant);
}
@@ -5511,7 +5466,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
- BuildCheckPrototypeMaps(prototype, object_prototype);
+ Add<HCheckPrototypeMaps>(prototype, object_prototype, top_info());
load_mode = ALLOW_RETURN_HOLE;
graph()->MarkDependsOnEmptyArrayProtoElements();
}
@@ -5724,8 +5679,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
// Deopt if none of the cases matched.
NoObservableSideEffectsScope scope(this);
- FinishExitWithHardDeoptimization("Unknown type in polymorphic element access",
- join);
+ FinishExitWithHardDeoptimization(join);
set_current_block(join);
return is_store ? NULL : Pop();
}
@@ -5761,14 +5715,12 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
} else {
if (is_store) {
if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) {
- Add<HDeoptimize>("Insufficient feedback for keyed store",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
}
instr = BuildStoreKeyedGeneric(obj, key, val);
} else {
if (expr->AsProperty()->IsUninitialized()) {
- Add<HDeoptimize>("Insufficient feedback for keyed load",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
}
instr = BuildLoadKeyedGeneric(obj, key);
}
@@ -5961,38 +5913,11 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
}
-void HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
- CompilationInfo* info) {
- HConstant* constant_value = New<HConstant>(constant);
-
- if (constant->map()->CanOmitMapChecks()) {
- constant->map()->AddDependentCompilationInfo(
- DependentCode::kPrototypeCheckGroup, info);
- return;
- }
-
- AddInstruction(constant_value);
- HCheckMaps* check =
- Add<HCheckMaps>(constant_value, handle(constant->map()), info);
- check->ClearGVNFlag(kDependsOnElementsKind);
-}
-
-
-void HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
- Handle<JSObject> holder) {
- BuildConstantMapCheck(prototype, top_info());
- while (!prototype.is_identical_to(holder)) {
- prototype = handle(JSObject::cast(prototype->GetPrototype()));
- BuildConstantMapCheck(prototype, top_info());
- }
-}
-
-
void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
Handle<Map> receiver_map) {
if (!holder.is_null()) {
Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
- BuildCheckPrototypeMaps(prototype, holder);
+ Add<HCheckPrototypeMaps>(prototype, holder, top_info());
}
}
@@ -6215,7 +6140,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
// that the environment stack matches the depth on deopt that it otherwise
// would have had after a successful call.
Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1));
- FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
+ FinishExitWithHardDeoptimization(join);
} else {
HValue* context = environment()->context();
HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
@@ -6364,7 +6289,7 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
if (target_info.isolate()->has_pending_exception()) {
// Parse or scope error, never optimize this function.
SetStackOverflow();
- target_shared->DisableOptimization(kParseScopeError);
+ target_shared->DisableOptimization("parse/scope error");
}
TraceInline(target, caller, "parse failure");
return false;
@@ -6503,7 +6428,7 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
// Bail out if the inline function did, as we cannot residualize a call
// instead.
TraceInline(target, caller, "inline graph construction failed");
- target_shared->DisableOptimization(kInliningBailedOut);
+ target_shared->DisableOptimization("inlining bailed out");
inline_bailout_ = true;
delete target_state;
return true;
@@ -6733,9 +6658,9 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
HValue* string = Pop();
HValue* context = environment()->context();
ASSERT(!expr->holder().is_null());
- BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck(
+ Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck(
STRING_CHECK, expr->holder()->GetIsolate()),
- expr->holder());
+ expr->holder(), top_info());
HInstruction* char_code =
BuildStringCharCodeAt(string, index);
if (id == kStringCharCodeAt) {
@@ -7048,7 +6973,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
} else {
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
- return Bailout(kPossibleDirectCallToEval);
+ return Bailout("possible direct call to eval");
}
bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
@@ -7316,7 +7241,7 @@ void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
if (expr->is_jsruntime()) {
- return Bailout(kCallToAJavaScriptRuntimeFunction);
+ return Bailout("call to a JavaScript runtime function");
}
const Runtime::Function* function = expr->function();
@@ -7356,6 +7281,8 @@ void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
case Token::DELETE: return VisitDelete(expr);
case Token::VOID: return VisitVoid(expr);
case Token::TYPEOF: return VisitTypeof(expr);
+ case Token::SUB: return VisitSub(expr);
+ case Token::BIT_NOT: return VisitBitNot(expr);
case Token::NOT: return VisitNot(expr);
default: UNREACHABLE();
}
@@ -7381,7 +7308,7 @@ void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
} else if (proxy != NULL) {
Variable* var = proxy->var();
if (var->IsUnallocated()) {
- Bailout(kDeleteWithGlobalVariable);
+ Bailout("delete with global variable");
} else if (var->IsStackAllocated() || var->IsContextSlot()) {
// Result of deleting non-global variables is false. 'this' is not
// really a variable, though we implement it as one. The
@@ -7391,7 +7318,7 @@ void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
: graph()->GetConstantFalse();
return ast_context()->ReturnValue(value);
} else {
- Bailout(kDeleteWithNonGlobalVariable);
+ Bailout("delete with non-global variable");
}
} else {
// Result of deleting non-property, non-variable reference is true.
@@ -7417,6 +7344,24 @@ void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
}
+void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
+ CHECK_ALIVE(VisitForValue(expr->expression()));
+ Handle<Type> operand_type = expr->expression()->bounds().lower;
+ HValue* value = TruncateToNumber(Pop(), &operand_type);
+ HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB);
+ return ast_context()->ReturnInstruction(instr, expr->id());
+}
+
+
+void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
+ CHECK_ALIVE(VisitForValue(expr->expression()));
+ Handle<Type> operand_type = expr->expression()->bounds().lower;
+ HValue* value = TruncateToNumber(Pop(), &operand_type);
+ HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT);
+ return ast_context()->ReturnInstruction(instr, expr->id());
+}
+
+
void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
if (ast_context()->IsTest()) {
TestContext* context = TestContext::cast(ast_context());
@@ -7505,7 +7450,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
VariableProxy* proxy = target->AsVariableProxy();
Property* prop = target->AsProperty();
if (proxy == NULL && prop == NULL) {
- return Bailout(kInvalidLhsInCountOperation);
+ return Bailout("invalid lhs in count operation");
}
// Match the full code generator stack by simulating an extra stack
@@ -7519,7 +7464,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
if (proxy != NULL) {
Variable* var = proxy->var();
if (var->mode() == CONST) {
- return Bailout(kUnsupportedCountOperationWithConst);
+ return Bailout("unsupported count operation with const");
}
// Argument of the count operation is a variable, not a property.
ASSERT(prop == NULL);
@@ -7553,7 +7498,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
int count = current_info()->scope()->num_parameters();
for (int i = 0; i < count; ++i) {
if (var == current_info()->scope()->parameter(i)) {
- return Bailout(kAssignmentToParameterInArgumentsObject);
+ return Bailout("assignment to parameter in arguments object");
}
}
}
@@ -7570,7 +7515,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
}
case Variable::LOOKUP:
- return Bailout(kLookupVariableInCountOperation);
+ return Bailout("lookup variable in count operation");
}
} else {
@@ -7613,7 +7558,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
after = BuildIncrement(returns_original_input, expr);
HValue* result = returns_original_input ? Pop() : after;
- return BuildStoreNamed(expr, expr->id(), expr->position(),
+ return BuildStoreNamed(prop, expr->id(), expr->position(),
expr->AssignmentId(), prop, object, after, result);
} else {
// Keyed property.
@@ -7775,14 +7720,12 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
}
if (left_type->Is(Type::None())) {
- Add<HDeoptimize>("Insufficient type feedback for left side",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
// TODO(rossberg): we should be able to get rid of non-continuous defaults.
left_type = handle(Type::Any(), isolate());
}
if (right_type->Is(Type::None())) {
- Add<HDeoptimize>("Insufficient type feedback for right side",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
right_type = handle(Type::Any(), isolate());
}
HInstruction* instr = NULL;
@@ -8132,8 +8075,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
// Cases handled below depend on collected type feedback. They should
// soft deoptimize when there is no type feedback.
if (combined_type->Is(Type::None())) {
- Add<HDeoptimize>("insufficient type feedback for combined type",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
combined_type = left_type = right_type = handle(Type::Any(), isolate());
}
@@ -8162,7 +8104,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
}
}
default:
- return Bailout(kUnsupportedNonPrimitiveCompare);
+ return Bailout("Unsupported non-primitive compare");
}
} else if (combined_type->Is(Type::InternalizedString()) &&
Token::IsEqualityOp(op)) {
@@ -8625,7 +8567,7 @@ void HOptimizedGraphBuilder::VisitVariableDeclaration(
}
break;
case Variable::LOOKUP:
- return Bailout(kUnsupportedLookupSlotInDeclaration);
+ return Bailout("unsupported lookup slot in declaration");
}
}
@@ -8663,7 +8605,7 @@ void HOptimizedGraphBuilder::VisitFunctionDeclaration(
break;
}
case Variable::LOOKUP:
- return Bailout(kUnsupportedLookupSlotInDeclaration);
+ return Bailout("unsupported lookup slot in declaration");
}
}
@@ -8784,7 +8726,7 @@ void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi);
+ return Bailout("inlined runtime function: IsNonNegativeSmi");
}
@@ -8800,7 +8742,8 @@ void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf);
+ return Bailout(
+ "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
}
@@ -8854,7 +8797,7 @@ void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) {
// The special form detected by IsClassOfTest is detected before we get here
// and does not cause a bailout.
- return Bailout(kInlinedRuntimeFunctionClassOf);
+ return Bailout("inlined runtime function: ClassOf");
}
@@ -9071,7 +9014,7 @@ void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
// Support for fast native caches.
void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionGetFromCache);
+ return Bailout("inlined runtime function: GetFromCache");
}
@@ -9201,7 +9144,7 @@ void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
// Check whether two RegExps are equivalent
void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent);
+ return Bailout("inlined runtime function: IsRegExpEquivalent");
}
@@ -9215,18 +9158,18 @@ void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionFastAsciiArrayJoin);
+ return Bailout("inlined runtime function: FastAsciiArrayJoin");
}
// Support for generators.
void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionGeneratorNext);
+ return Bailout("inlined runtime function: GeneratorNext");
}
void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionGeneratorThrow);
+ return Bailout("inlined runtime function: GeneratorThrow");
}