Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(927)

Unified Diff: src/hydrogen.cc

Issue 22715004: Version 3.20.15 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Add TypedArray API and correctness patches r16033 and r16084 Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-dehoist.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 837c9780c50abe3753ddfd8c86d60a45626405f8..7ec65df28ddcf9d3d6866473dbfb5226f0359475 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -957,9 +957,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
@@ -1050,14 +1049,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();
}
@@ -1719,6 +1716,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,
@@ -2549,7 +2578,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);
}
@@ -2601,7 +2630,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);
@@ -2614,7 +2643,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();
@@ -2704,7 +2733,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);
@@ -2750,7 +2779,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();
}
@@ -2809,16 +2838,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);
@@ -2884,7 +2913,8 @@ bool HOptimizedGraphBuilder::BuildGraph() {
}
-bool HGraph::Optimize(BailoutReason* bailout_reason) {
+bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
+ *bailout_reason = SmartArrayPointer<char>();
OrderBlocks();
AssignDominators();
@@ -2905,12 +2935,14 @@ 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;
}
@@ -2950,10 +2982,11 @@ bool HGraph::Optimize(BailoutReason* bailout_reason) {
// 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>();
@@ -2965,6 +2998,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);
@@ -3047,7 +3124,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(),
@@ -3068,7 +3145,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);
@@ -3280,7 +3357,7 @@ void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kWithStatement);
+ return Bailout("WithStatement");
}
@@ -3295,12 +3372,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();
@@ -3592,16 +3669,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();
@@ -3695,7 +3772,7 @@ void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kForOfStatement);
+ return Bailout("ForOfStatement");
}
@@ -3703,7 +3780,7 @@ void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kTryCatchStatement);
+ return Bailout("TryCatchStatement");
}
@@ -3712,7 +3789,7 @@ void HOptimizedGraphBuilder::VisitTryFinallyStatement(
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kTryFinallyStatement);
+ return Bailout("TryFinallyStatement");
}
@@ -3720,7 +3797,7 @@ void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kDebuggerStatement);
+ return Bailout("DebuggerStatement");
}
@@ -3766,7 +3843,7 @@ void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral(
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kSharedFunctionInfoLiteral);
+ return Bailout("SharedFunctionInfoLiteral");
}
@@ -3846,7 +3923,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.
@@ -3903,7 +3980,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);
}
@@ -3915,7 +3992,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
}
case Variable::LOOKUP:
- return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
+ return Bailout("reference to a variable which requires dynamic lookup");
}
}
@@ -4036,7 +4113,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;
}
@@ -4213,7 +4291,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();
}
}
@@ -4252,7 +4330,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();
@@ -4343,7 +4421,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);
@@ -4423,7 +4501,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.
@@ -4436,9 +4514,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);
@@ -4476,8 +4554,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);
@@ -4593,7 +4670,8 @@ 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));
@@ -4927,7 +5005,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));
@@ -4943,7 +5021,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;
@@ -4959,7 +5037,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");
}
}
}
@@ -4990,7 +5069,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
}
case Variable::LOOKUP:
- return Bailout(kCompoundAssignmentToLookupSlot);
+ return Bailout("compound assignment to lookup slot");
}
return ast_context()->ReturnValue(Pop());
@@ -5079,7 +5158,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
}
} else {
- return Bailout(kInvalidLhsInCompoundAssignment);
+ return Bailout("invalid lhs in compound assignment");
}
}
@@ -5116,11 +5195,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()) {
@@ -5139,7 +5218,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
@@ -5161,7 +5240,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");
}
}
}
@@ -5202,10 +5281,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");
}
}
@@ -5327,7 +5406,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());
HValue* holder_value = Add<HConstant>(holder);
return BuildLoadNamedField(holder_value,
HObjectAccess::ForField(holder_map, &lookup, name));
@@ -5339,7 +5418,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);
}
@@ -5375,7 +5454,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();
}
@@ -5821,38 +5900,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());
}
}
@@ -6224,7 +6276,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;
@@ -6363,7 +6415,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;
@@ -6593,9 +6645,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) {
@@ -6908,7 +6960,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();
@@ -7176,7 +7228,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();
@@ -7216,6 +7268,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();
}
@@ -7241,7 +7295,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
@@ -7251,7 +7305,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.
@@ -7277,6 +7331,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());
@@ -7365,7 +7437,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
@@ -7379,7 +7451,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);
@@ -7413,7 +7485,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");
}
}
}
@@ -7430,7 +7502,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
}
case Variable::LOOKUP:
- return Bailout(kLookupVariableInCountOperation);
+ return Bailout("lookup variable in count operation");
}
} else {
@@ -8019,7 +8091,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)) {
@@ -8486,7 +8558,7 @@ void HOptimizedGraphBuilder::VisitVariableDeclaration(
}
break;
case Variable::LOOKUP:
- return Bailout(kUnsupportedLookupSlotInDeclaration);
+ return Bailout("unsupported lookup slot in declaration");
}
}
@@ -8524,7 +8596,7 @@ void HOptimizedGraphBuilder::VisitFunctionDeclaration(
break;
}
case Variable::LOOKUP:
- return Bailout(kUnsupportedLookupSlotInDeclaration);
+ return Bailout("unsupported lookup slot in declaration");
}
}
@@ -8645,7 +8717,7 @@ void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi);
+ return Bailout("inlined runtime function: IsNonNegativeSmi");
}
@@ -8661,7 +8733,8 @@ void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf);
+ return Bailout(
+ "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
}
@@ -8715,7 +8788,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");
}
@@ -8932,7 +9005,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");
}
@@ -9062,7 +9135,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");
}
@@ -9076,18 +9149,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");
}
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-dehoist.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698