diff options
Diffstat (limited to 'chromium/v8/src/hydrogen.cc')
-rw-r--r-- | chromium/v8/src/hydrogen.cc | 501 |
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"); } |