summaryrefslogtreecommitdiff
path: root/deps/v8/src/hydrogen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/hydrogen.cc')
-rw-r--r--deps/v8/src/hydrogen.cc437
1 files changed, 158 insertions, 279 deletions
diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc
index 2d471cc29..c625fba8d 100644
--- a/deps/v8/src/hydrogen.cc
+++ b/deps/v8/src/hydrogen.cc
@@ -422,7 +422,7 @@ class ReachabilityAnalyzer BASE_EMBEDDED {
};
-void HGraph::Verify(bool do_full_verify) const {
+void HGraph::Verify() const {
for (int i = 0; i < blocks_.length(); i++) {
HBasicBlock* block = blocks_.at(i);
@@ -473,27 +473,25 @@ void HGraph::Verify(bool do_full_verify) const {
// Check special property of first block to have no predecessors.
ASSERT(blocks_.at(0)->predecessors()->is_empty());
- if (do_full_verify) {
- // Check that the graph is fully connected.
- ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
- ASSERT(analyzer.visited_count() == blocks_.length());
+ // Check that the graph is fully connected.
+ ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
+ ASSERT(analyzer.visited_count() == blocks_.length());
- // Check that entry block dominator is NULL.
- ASSERT(entry_block_->dominator() == NULL);
+ // Check that entry block dominator is NULL.
+ ASSERT(entry_block_->dominator() == NULL);
- // Check dominators.
- for (int i = 0; i < blocks_.length(); ++i) {
- HBasicBlock* block = blocks_.at(i);
- if (block->dominator() == NULL) {
- // Only start block may have no dominator assigned to.
- ASSERT(i == 0);
- } else {
- // Assert that block is unreachable if dominator must not be visited.
- ReachabilityAnalyzer dominator_analyzer(entry_block_,
- blocks_.length(),
- block->dominator());
- ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id()));
- }
+ // Check dominators.
+ for (int i = 0; i < blocks_.length(); ++i) {
+ HBasicBlock* block = blocks_.at(i);
+ if (block->dominator() == NULL) {
+ // Only start block may have no dominator assigned to.
+ ASSERT(i == 0);
+ } else {
+ // Assert that block is unreachable if dominator must not be visited.
+ ReachabilityAnalyzer dominator_analyzer(entry_block_,
+ blocks_.length(),
+ block->dominator());
+ ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id()));
}
}
}
@@ -852,7 +850,7 @@ void HGraph::EliminateUnreachablePhis() {
}
-bool HGraph::CheckArgumentsPhiUses() {
+bool HGraph::CheckPhis() {
int block_count = blocks_.length();
for (int i = 0; i < block_count; ++i) {
for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
@@ -865,11 +863,13 @@ bool HGraph::CheckArgumentsPhiUses() {
}
-bool HGraph::CheckConstPhiUses() {
+bool HGraph::CollectPhis() {
int block_count = blocks_.length();
+ phi_list_ = new ZoneList<HPhi*>(block_count);
for (int i = 0; i < block_count; ++i) {
for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
HPhi* phi = blocks_[i]->phis()->at(j);
+ phi_list_->Add(phi);
// Check for the hole value (from an uninitialized const).
for (int k = 0; k < phi->OperandCount(); k++) {
if (phi->OperandAt(k) == GetConstantHole()) return false;
@@ -880,18 +880,6 @@ bool HGraph::CheckConstPhiUses() {
}
-void HGraph::CollectPhis() {
- int block_count = blocks_.length();
- phi_list_ = new ZoneList<HPhi*>(block_count);
- for (int i = 0; i < block_count; ++i) {
- for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
- HPhi* phi = blocks_[i]->phis()->at(j);
- phi_list_->Add(phi);
- }
- }
-}
-
-
void HGraph::InferTypes(ZoneList<HValue*>* worklist) {
BitVector in_worklist(GetMaximumValueID());
for (int i = 0; i < worklist->length(); ++i) {
@@ -1499,6 +1487,9 @@ int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
block->block_id() < dominated->block_id() &&
visited_on_paths_.Add(block->block_id())) {
side_effects |= block_side_effects_[block->block_id()];
+ if (block->IsLoopHeader()) {
+ side_effects |= loop_side_effects_[block->block_id()];
+ }
side_effects |= CollectSideEffectsOnPathsToDominatedBlock(
dominator, block);
}
@@ -1860,7 +1851,7 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value,
}
if (new_value == NULL) {
- new_value = new(zone()) HChange(value, to,
+ new_value = new(zone()) HChange(value, value->representation(), to,
is_truncating, deoptimize_on_undefined);
}
@@ -2311,7 +2302,7 @@ HGraph* HGraphBuilder::CreateGraph() {
// Handle implicit declaration of the function name in named function
// expressions before other declarations.
if (scope->is_function_scope() && scope->function() != NULL) {
- HandleDeclaration(scope->function(), CONST, NULL);
+ HandleDeclaration(scope->function(), Variable::CONST, NULL);
}
VisitDeclarations(scope->declarations());
AddSimulate(AstNode::kDeclarationsId);
@@ -2332,24 +2323,17 @@ HGraph* HGraphBuilder::CreateGraph() {
graph()->OrderBlocks();
graph()->AssignDominators();
-
-#ifdef DEBUG
- // Do a full verify after building the graph and computing dominators.
- graph()->Verify(true);
-#endif
-
graph()->PropagateDeoptimizingMark();
- if (!graph()->CheckConstPhiUses()) {
- Bailout("Unsupported phi use of const variable");
- return NULL;
- }
graph()->EliminateRedundantPhis();
- if (!graph()->CheckArgumentsPhiUses()) {
- Bailout("Unsupported phi use of arguments");
+ if (!graph()->CheckPhis()) {
+ Bailout("Unsupported phi use of arguments object");
return NULL;
}
if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
- graph()->CollectPhis();
+ if (!graph()->CollectPhis()) {
+ Bailout("Unsupported phi use of uninitialized constant");
+ return NULL;
+ }
HInferRepresentation rep(graph());
rep.Analyze();
@@ -3141,21 +3125,11 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
Variable* variable = expr->var();
- if (variable->mode() == LET) {
+ if (variable->mode() == Variable::LET) {
return Bailout("reference to let variable");
}
switch (variable->location()) {
case Variable::UNALLOCATED: {
- // Handle known global constants like 'undefined' specially to avoid a
- // load from a global cell for them.
- Handle<Object> constant_value =
- isolate()->factory()->GlobalConstantFor(variable->name());
- if (!constant_value.is_null()) {
- HConstant* instr =
- new(zone()) HConstant(constant_value, Representation::Tagged());
- return ast_context()->ReturnInstruction(instr, expr->id());
- }
-
LookupResult lookup;
GlobalPropertyAccess type =
LookupGlobalProperty(variable, &lookup, false);
@@ -3168,8 +3142,8 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
if (type == kUseCell) {
Handle<GlobalObject> global(info()->global_object());
Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
- HLoadGlobalCell* instr =
- new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
+ bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
+ HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole);
return ast_context()->ReturnInstruction(instr, expr->id());
} else {
HValue* context = environment()->LookupContext();
@@ -3188,7 +3162,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
case Variable::PARAMETER:
case Variable::LOCAL: {
HValue* value = environment()->Lookup(variable);
- if (variable->mode() == CONST &&
+ if (variable->mode() == Variable::CONST &&
value == graph()->GetConstantHole()) {
return Bailout("reference to uninitialized const variable");
}
@@ -3196,7 +3170,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
}
case Variable::CONTEXT: {
- if (variable->mode() == CONST) {
+ if (variable->mode() == Variable::CONST) {
return Bailout("reference to const context slot");
}
HValue* context = BuildContextChainWalk(variable);
@@ -3346,43 +3320,7 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
HValue* key = AddInstruction(
new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)),
Representation::Integer32()));
- HInstruction* elements_kind =
- AddInstruction(new(zone()) HElementsKind(literal));
- HBasicBlock* store_fast = graph()->CreateBasicBlock();
- // Two empty blocks to satisfy edge split form.
- HBasicBlock* store_fast_edgesplit1 = graph()->CreateBasicBlock();
- HBasicBlock* store_fast_edgesplit2 = graph()->CreateBasicBlock();
- HBasicBlock* store_generic = graph()->CreateBasicBlock();
- HBasicBlock* check_smi_only_elements = graph()->CreateBasicBlock();
- HBasicBlock* join = graph()->CreateBasicBlock();
-
- HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(value);
- smicheck->SetSuccessorAt(0, store_fast_edgesplit1);
- smicheck->SetSuccessorAt(1, check_smi_only_elements);
- current_block()->Finish(smicheck);
- store_fast_edgesplit1->Finish(new(zone()) HGoto(store_fast));
-
- set_current_block(check_smi_only_elements);
- HCompareConstantEqAndBranch* smi_elements_check =
- new(zone()) HCompareConstantEqAndBranch(elements_kind,
- FAST_SMI_ONLY_ELEMENTS,
- Token::EQ_STRICT);
- smi_elements_check->SetSuccessorAt(0, store_generic);
- smi_elements_check->SetSuccessorAt(1, store_fast_edgesplit2);
- current_block()->Finish(smi_elements_check);
- store_fast_edgesplit2->Finish(new(zone()) HGoto(store_fast));
-
- set_current_block(store_fast);
AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value));
- store_fast->Goto(join);
-
- set_current_block(store_generic);
- AddInstruction(BuildStoreKeyedGeneric(literal, key, value));
- store_generic->Goto(join);
-
- join->SetJoinId(expr->id());
- set_current_block(join);
-
AddSimulate(expr->GetIdForElement(i));
}
return ast_context()->ReturnValue(Pop());
@@ -3626,10 +3564,10 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
LookupResult lookup;
GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
if (type == kUseCell) {
+ bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
Handle<GlobalObject> global(info()->global_object());
Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
- HInstruction* instr =
- new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails());
+ HInstruction* instr = new(zone()) HStoreGlobalCell(value, cell, check_hole);
instr->set_position(position);
AddInstruction(instr);
if (instr->HasSideEffects()) AddSimulate(ast_id);
@@ -3663,7 +3601,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
if (proxy != NULL) {
Variable* var = proxy->var();
- if (var->mode() == CONST || var->mode() == LET) {
+ if (var->mode() == Variable::CONST || var->mode() == Variable::LET) {
return Bailout("unsupported let or const compound assignment");
}
@@ -3808,7 +3746,7 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
HandlePropertyAssignment(expr);
} else if (proxy != NULL) {
Variable* var = proxy->var();
- if (var->mode() == CONST) {
+ if (var->mode() == Variable::CONST) {
if (expr->op() != Token::INIT_CONST) {
return Bailout("non-initializer assignment to const");
}
@@ -3819,7 +3757,7 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
// variables (e.g. initialization inside a loop).
HValue* old_value = environment()->Lookup(var);
AddInstruction(new HUseConst(old_value));
- } else if (var->mode() == LET) {
+ } else if (var->mode() == Variable::LET) {
return Bailout("unsupported assignment to let");
}
@@ -3847,7 +3785,7 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
}
case Variable::CONTEXT: {
- ASSERT(var->mode() != CONST);
+ ASSERT(var->mode() != Variable::CONST);
// Bail out if we try to mutate a parameter value in a function using
// the arguments object. We do not (yet) correctly handle the
// arguments property of the function.
@@ -3993,7 +3931,6 @@ HInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
break;
- case FAST_SMI_ONLY_ELEMENTS:
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
case DICTIONARY_ELEMENTS:
@@ -4010,30 +3947,6 @@ HInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
}
-HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
- HValue* checked_key,
- HValue* val,
- ElementsKind elements_kind,
- bool is_store) {
- if (is_store) {
- ASSERT(val != NULL);
- if (elements_kind == FAST_DOUBLE_ELEMENTS) {
- return new(zone()) HStoreKeyedFastDoubleElement(
- elements, checked_key, val);
- } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS.
- return new(zone()) HStoreKeyedFastElement(
- elements, checked_key, val, elements_kind);
- }
- }
- // It's an element load (!is_store).
- if (elements_kind == FAST_DOUBLE_ELEMENTS) {
- return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
- } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS.
- return new(zone()) HLoadKeyedFastElement(elements, checked_key);
- }
-}
-
-
HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
HValue* key,
HValue* val,
@@ -4041,20 +3954,17 @@ HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
bool is_store) {
ASSERT(expr->IsMonomorphic());
Handle<Map> map = expr->GetMonomorphicReceiverType();
- AddInstruction(new(zone()) HCheckNonSmi(object));
- HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map));
- bool fast_smi_only_elements = map->has_fast_smi_only_elements();
- bool fast_elements = map->has_fast_elements();
- bool fast_double_elements = map->has_fast_double_elements();
- if (!fast_smi_only_elements &&
- !fast_elements &&
- !fast_double_elements &&
+ if (!map->has_fast_elements() &&
+ !map->has_fast_double_elements() &&
!map->has_external_array_elements()) {
return is_store ? BuildStoreKeyedGeneric(object, key, val)
: BuildLoadKeyedGeneric(object, key);
}
+ AddInstruction(new(zone()) HCheckNonSmi(object));
+ HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map));
HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
- if (is_store && (fast_elements || fast_smi_only_elements)) {
+ bool fast_double_elements = map->has_fast_double_elements();
+ if (is_store && map->has_fast_elements()) {
AddInstruction(new(zone()) HCheckMap(
elements, isolate()->factory()->fixed_array_map()));
}
@@ -4069,15 +3979,28 @@ HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
return BuildExternalArrayElementAccess(external_elements, checked_key,
val, map->elements_kind(), is_store);
}
- ASSERT(fast_smi_only_elements || fast_elements || fast_double_elements);
+ ASSERT(map->has_fast_elements() || fast_double_elements);
if (map->instance_type() == JS_ARRAY_TYPE) {
length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck));
} else {
length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
}
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
- return BuildFastElementAccess(elements, checked_key, val,
- map->elements_kind(), is_store);
+ if (is_store) {
+ if (fast_double_elements) {
+ return new(zone()) HStoreKeyedFastDoubleElement(elements,
+ checked_key,
+ val);
+ } else {
+ return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
+ }
+ } else {
+ if (fast_double_elements) {
+ return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
+ } else {
+ return new(zone()) HLoadKeyedFastElement(elements, checked_key);
+ }
+ }
}
@@ -4119,20 +4042,14 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
HLoadExternalArrayPointer* external_elements = NULL;
HInstruction* checked_key = NULL;
- // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS,
- // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS are handled before external
- // arrays.
- STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
- STATIC_ASSERT(FAST_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
- STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
- STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
+ // FAST_ELEMENTS is assumed to be the first case.
+ STATIC_ASSERT(FAST_ELEMENTS == 0);
- for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND;
+ for (ElementsKind elements_kind = FAST_ELEMENTS;
elements_kind <= LAST_ELEMENTS_KIND;
elements_kind = ElementsKind(elements_kind + 1)) {
- // After having handled FAST_ELEMENTS, FAST_SMI_ONLY_ELEMENTS,
- // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS, we need to add some code
- // that's executed for all external array cases.
+ // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we
+ // need to add some code that's executed for all external array cases.
STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND ==
LAST_ELEMENTS_KIND);
if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
@@ -4154,25 +4071,15 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
set_current_block(if_true);
HInstruction* access;
- if (elements_kind == FAST_SMI_ONLY_ELEMENTS ||
- elements_kind == FAST_ELEMENTS ||
+ if (elements_kind == FAST_ELEMENTS ||
elements_kind == FAST_DOUBLE_ELEMENTS) {
- if (is_store && elements_kind == FAST_SMI_ONLY_ELEMENTS) {
- AddInstruction(new(zone()) HCheckSmi(val));
- }
- if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) {
+ bool fast_double_elements =
+ elements_kind == FAST_DOUBLE_ELEMENTS;
+ if (is_store && elements_kind == FAST_ELEMENTS) {
AddInstruction(new(zone()) HCheckMap(
elements, isolate()->factory()->fixed_array_map(),
elements_kind_branch));
}
- // TODO(jkummerow): The need for these two blocks could be avoided
- // in one of two ways:
- // (1) Introduce ElementsKinds for JSArrays that are distinct from
- // those for fast objects.
- // (2) Put the common instructions into a third "join" block. This
- // requires additional AST IDs that we can deopt to from inside
- // that join block. They must be added to the Property class (when
- // it's a keyed property) and registered in the full codegen.
HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
HHasInstanceTypeAndBranch* typecheck =
@@ -4182,15 +4089,29 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
current_block()->Finish(typecheck);
set_current_block(if_jsarray);
- HInstruction* length;
- length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck));
+ HInstruction* length = new(zone()) HJSArrayLength(object, typecheck);
+ AddInstruction(length);
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
- access = AddInstruction(BuildFastElementAccess(
- elements, checked_key, val, elements_kind, is_store));
- if (!is_store) {
+ if (is_store) {
+ if (fast_double_elements) {
+ access = AddInstruction(
+ new(zone()) HStoreKeyedFastDoubleElement(elements,
+ checked_key,
+ val));
+ } else {
+ access = AddInstruction(
+ new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
+ }
+ } else {
+ if (fast_double_elements) {
+ access = AddInstruction(
+ new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
+ } else {
+ access = AddInstruction(
+ new(zone()) HLoadKeyedFastElement(elements, checked_key));
+ }
Push(access);
}
-
*has_side_effects |= access->HasSideEffects();
if (position != -1) {
access->set_position(position);
@@ -4200,8 +4121,25 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
set_current_block(if_fastobject);
length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
- access = AddInstruction(BuildFastElementAccess(
- elements, checked_key, val, elements_kind, is_store));
+ if (is_store) {
+ if (fast_double_elements) {
+ access = AddInstruction(
+ new(zone()) HStoreKeyedFastDoubleElement(elements,
+ checked_key,
+ val));
+ } else {
+ access = AddInstruction(
+ new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
+ }
+ } else {
+ if (fast_double_elements) {
+ access = AddInstruction(
+ new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
+ } else {
+ access = AddInstruction(
+ new(zone()) HLoadKeyedFastElement(elements, checked_key));
+ }
+ }
} else if (elements_kind == DICTIONARY_ELEMENTS) {
if (is_store) {
access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
@@ -4539,25 +4477,20 @@ bool HGraphBuilder::TryInline(Call* expr) {
return false;
}
+ // No context change required.
CompilationInfo* outer_info = info();
-#if !defined(V8_TARGET_ARCH_IA32)
- // Target must be able to use caller's context.
if (target->context() != outer_info->closure()->context() ||
outer_info->scope()->contains_with() ||
outer_info->scope()->num_heap_slots() > 0) {
TraceInline(target, caller, "target requires context change");
return false;
}
-#endif
-
// Don't inline deeper than kMaxInliningLevels calls.
HEnvironment* env = environment();
int current_level = 1;
while (env->outer() != NULL) {
- if (current_level == (FLAG_limit_inlining
- ? Compiler::kMaxInliningLevels
- : 2 * Compiler::kMaxInliningLevels)) {
+ if (current_level == Compiler::kMaxInliningLevels) {
TraceInline(target, caller, "inline depth limit reached");
return false;
}
@@ -4663,8 +4596,7 @@ bool HGraphBuilder::TryInline(Call* expr) {
ASSERT(target_shared->has_deoptimization_support());
TypeFeedbackOracle target_oracle(
Handle<Code>(target_shared->code()),
- Handle<Context>(target->context()->global_context()),
- isolate());
+ Handle<Context>(target->context()->global_context()));
FunctionState target_state(this, &target_info, &target_oracle);
HConstant* undefined = graph()->GetConstantUndefined();
@@ -4673,17 +4605,6 @@ bool HGraphBuilder::TryInline(Call* expr) {
function,
undefined,
call_kind);
-#ifdef V8_TARGET_ARCH_IA32
- // IA32 only, overwrite the caller's context in the deoptimization
- // environment with the correct one.
- //
- // TODO(kmillikin): implement the same inlining on other platforms so we
- // can remove the unsightly ifdefs in this function.
- HConstant* context = new HConstant(Handle<Context>(target->context()),
- Representation::Tagged());
- AddInstruction(context);
- inner_env->BindContext(context);
-#endif
HBasicBlock* body_entry = CreateBasicBlock(inner_env);
current_block()->Goto(body_entry);
body_entry->SetJoinId(expr->ReturnId());
@@ -5004,8 +4925,8 @@ void HGraphBuilder::VisitCall(Call* expr) {
}
} else {
- expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION);
VariableProxy* proxy = expr->expression()->AsVariableProxy();
+ // FIXME.
bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
if (global_call) {
@@ -5057,46 +4978,6 @@ void HGraphBuilder::VisitCall(Call* expr) {
Drop(argument_count);
}
- } else if (expr->IsMonomorphic()) {
- // The function is on the stack in the unoptimized code during
- // evaluation of the arguments.
- CHECK_ALIVE(VisitForValue(expr->expression()));
- HValue* function = Top();
- HValue* context = environment()->LookupContext();
- HGlobalObject* global = new(zone()) HGlobalObject(context);
- HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global);
- AddInstruction(global);
- PushAndAdd(receiver);
- CHECK_ALIVE(VisitExpressions(expr->arguments()));
- AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
- if (TryInline(expr)) {
- // The function is lingering in the deoptimization environment.
- // Handle it by case analysis on the AST context.
- if (ast_context()->IsEffect()) {
- Drop(1);
- } else if (ast_context()->IsValue()) {
- HValue* result = Pop();
- Drop(1);
- Push(result);
- } else if (ast_context()->IsTest()) {
- TestContext* context = TestContext::cast(ast_context());
- if (context->if_true()->HasPredecessor()) {
- context->if_true()->last_environment()->Drop(1);
- }
- if (context->if_false()->HasPredecessor()) {
- context->if_true()->last_environment()->Drop(1);
- }
- } else {
- UNREACHABLE();
- }
- return;
- } else {
- call = PreProcessCall(new(zone()) HInvokeFunction(context,
- function,
- argument_count));
- Drop(1); // The function.
- }
-
} else {
CHECK_ALIVE(VisitArgument(expr->expression()));
HValue* context = environment()->LookupContext();
@@ -5403,7 +5284,7 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
if (proxy != NULL) {
Variable* var = proxy->var();
- if (var->mode() == CONST) {
+ if (var->mode() == Variable::CONST) {
return Bailout("unsupported count operation with const");
}
// Argument of the count operation is a variable, not a property.
@@ -5790,36 +5671,26 @@ Representation HGraphBuilder::ToRepresentation(TypeInfo info) {
}
-void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
- Expression* sub_expr,
+void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* compare_expr,
+ Expression* expr,
Handle<String> check) {
- CHECK_ALIVE(VisitForTypeOf(sub_expr));
- HValue* value = Pop();
- HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check);
- instr->set_position(expr->position());
- return ast_context()->ReturnControl(instr, expr->id());
+ CHECK_ALIVE(VisitForTypeOf(expr));
+ HValue* expr_value = Pop();
+ HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(expr_value, check);
+ instr->set_position(compare_expr->position());
+ return ast_context()->ReturnControl(instr, compare_expr->id());
}
-bool HGraphBuilder::TryLiteralCompare(CompareOperation* expr) {
- Expression *sub_expr;
- Handle<String> check;
- if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
- HandleLiteralCompareTypeof(expr, sub_expr, check);
- return true;
- }
-
- if (expr->IsLiteralCompareUndefined(&sub_expr)) {
- HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
- return true;
- }
-
- if (expr->IsLiteralCompareNull(&sub_expr)) {
- HandleLiteralCompareNil(expr, sub_expr, kNullValue);
- return true;
- }
-
- return false;
+void HGraphBuilder::HandleLiteralCompareUndefined(
+ CompareOperation* compare_expr, Expression* expr) {
+ CHECK_ALIVE(VisitForValue(expr));
+ HValue* lhs = Pop();
+ HValue* rhs = graph()->GetConstantUndefined();
+ HCompareObjectEqAndBranch* instr =
+ new(zone()) HCompareObjectEqAndBranch(lhs, rhs);
+ instr->set_position(compare_expr->position());
+ return ast_context()->ReturnControl(instr, compare_expr->id());
}
@@ -5841,7 +5712,17 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
}
// Check for special cases that compare against literals.
- if (TryLiteralCompare(expr)) return;
+ Expression *sub_expr;
+ Handle<String> check;
+ if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
+ HandleLiteralCompareTypeof(expr, sub_expr, check);
+ return;
+ }
+
+ if (expr->IsLiteralCompareUndefined(&sub_expr)) {
+ HandleLiteralCompareUndefined(expr, sub_expr);
+ return;
+ }
TypeInfo type_info = oracle()->CompareType(expr);
// Check if this expression was ever executed according to type feedback.
@@ -5946,18 +5827,14 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
}
-void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
- Expression* sub_expr,
- NilValue nil) {
+void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- CHECK_ALIVE(VisitForValue(sub_expr));
+ CHECK_ALIVE(VisitForValue(expr->expression()));
HValue* value = Pop();
- EqualityKind kind =
- expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality;
- HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil);
- instr->set_position(expr->position());
+ HIsNullAndBranch* instr =
+ new(zone()) HIsNullAndBranch(value, expr->is_strict());
return ast_context()->ReturnControl(instr, expr->id());
}
@@ -5977,9 +5854,9 @@ void HGraphBuilder::VisitDeclaration(Declaration* decl) {
void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
- VariableMode mode,
+ Variable::Mode mode,
FunctionLiteral* function) {
- if (mode == LET) return Bailout("unsupported let declaration");
+ if (mode == Variable::LET) return Bailout("unsupported let declaration");
Variable* var = proxy->var();
switch (var->location()) {
case Variable::UNALLOCATED:
@@ -5987,9 +5864,9 @@ void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
case Variable::PARAMETER:
case Variable::LOCAL:
case Variable::CONTEXT:
- if (mode == CONST || function != NULL) {
+ if (mode == Variable::CONST || function != NULL) {
HValue* value = NULL;
- if (mode == CONST) {
+ if (mode == Variable::CONST) {
value = graph()->GetConstantHole();
} else {
VisitForValue(function);
@@ -6040,7 +5917,9 @@ void HGraphBuilder::GenerateIsFunction(CallRuntime* call) {
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
HValue* value = Pop();
HHasInstanceTypeAndBranch* result =
- new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE);
+ new(zone()) HHasInstanceTypeAndBranch(value,
+ JS_FUNCTION_TYPE,
+ JS_FUNCTION_PROXY_TYPE);
return ast_context()->ReturnControl(result, call->id());
}
@@ -6940,7 +6819,7 @@ void HPhase::End() const {
}
#ifdef DEBUG
- if (graph_ != NULL) graph_->Verify(false); // No full verify.
+ if (graph_ != NULL) graph_->Verify();
if (allocator_ != NULL) allocator_->Verify();
#endif
}