OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 #endif | 68 #endif |
69 | 69 |
70 namespace v8 { | 70 namespace v8 { |
71 namespace internal { | 71 namespace internal { |
72 | 72 |
73 const auto GetRegConfig = RegisterConfiguration::Crankshaft; | 73 const auto GetRegConfig = RegisterConfiguration::Crankshaft; |
74 | 74 |
75 class HOptimizedGraphBuilderWithPositions : public HOptimizedGraphBuilder { | 75 class HOptimizedGraphBuilderWithPositions : public HOptimizedGraphBuilder { |
76 public: | 76 public: |
77 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) | 77 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) |
78 : HOptimizedGraphBuilder(info) {} | 78 : HOptimizedGraphBuilder(info, true) { |
| 79 SetSourcePosition(info->shared_info()->start_position()); |
| 80 } |
79 | 81 |
80 #define DEF_VISIT(type) \ | 82 #define DEF_VISIT(type) \ |
81 void Visit##type(type* node) override { \ | 83 void Visit##type(type* node) override { \ |
82 SourcePosition old_position = SourcePosition::Unknown(); \ | 84 SourcePosition old_position = SourcePosition::Unknown(); \ |
83 if (node->position() != kNoSourcePosition) { \ | 85 if (node->position() != kNoSourcePosition) { \ |
84 old_position = source_position(); \ | 86 old_position = source_position(); \ |
85 SetSourcePosition(node->position()); \ | 87 SetSourcePosition(node->position()); \ |
86 } \ | 88 } \ |
87 HOptimizedGraphBuilder::Visit##type(node); \ | 89 HOptimizedGraphBuilder::Visit##type(node); \ |
88 if (!old_position.IsUnknown()) { \ | 90 if (!old_position.IsUnknown()) { \ |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 } | 173 } |
172 | 174 |
173 // Optimization could have been disabled by the parser. Note that this check | 175 // Optimization could have been disabled by the parser. Note that this check |
174 // is only needed because the Hydrogen graph builder is missing some bailouts. | 176 // is only needed because the Hydrogen graph builder is missing some bailouts. |
175 if (info()->shared_info()->optimization_disabled()) { | 177 if (info()->shared_info()->optimization_disabled()) { |
176 return AbortOptimization( | 178 return AbortOptimization( |
177 info()->shared_info()->disable_optimization_reason()); | 179 info()->shared_info()->disable_optimization_reason()); |
178 } | 180 } |
179 | 181 |
180 HOptimizedGraphBuilder* graph_builder = | 182 HOptimizedGraphBuilder* graph_builder = |
181 (info()->is_tracking_positions() || FLAG_trace_ic) | 183 (FLAG_hydrogen_track_positions || isolate()->is_profiling() || |
| 184 FLAG_trace_ic) |
182 ? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info()) | 185 ? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info()) |
183 : new (info()->zone()) HOptimizedGraphBuilder(info()); | 186 : new (info()->zone()) HOptimizedGraphBuilder(info(), false); |
184 | 187 |
185 // Type-check the function. | 188 // Type-check the function. |
186 AstTyper(info()->isolate(), info()->zone(), info()->closure(), | 189 AstTyper(info()->isolate(), info()->zone(), info()->closure(), |
187 info()->scope(), info()->osr_ast_id(), info()->literal(), | 190 info()->scope(), info()->osr_ast_id(), info()->literal(), |
188 graph_builder->bounds()) | 191 graph_builder->bounds()) |
189 .Run(); | 192 .Run(); |
190 | 193 |
191 graph_ = graph_builder->CreateGraph(); | 194 graph_ = graph_builder->CreateGraph(); |
192 | 195 |
193 if (isolate()->has_pending_exception()) { | 196 if (isolate()->has_pending_exception()) { |
(...skipping 1161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1355 builder_->set_current_block(exit_block_); | 1358 builder_->set_current_block(exit_block_); |
1356 } | 1359 } |
1357 finished_ = true; | 1360 finished_ = true; |
1358 } | 1361 } |
1359 | 1362 |
1360 | 1363 |
1361 HGraph* HGraphBuilder::CreateGraph() { | 1364 HGraph* HGraphBuilder::CreateGraph() { |
1362 DCHECK(!FLAG_minimal); | 1365 DCHECK(!FLAG_minimal); |
1363 graph_ = new (zone()) HGraph(info_, descriptor_); | 1366 graph_ = new (zone()) HGraph(info_, descriptor_); |
1364 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); | 1367 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); |
1365 if (!info_->IsStub() && info_->is_tracking_positions()) { | 1368 if (!info_->IsStub() && is_tracking_positions()) { |
1366 TraceInlinedFunction(info_->shared_info(), SourcePosition::Unknown()); | 1369 TraceInlinedFunction(info_->shared_info(), SourcePosition::Unknown()); |
1367 } | 1370 } |
1368 CompilationPhase phase("H_Block building", info_); | 1371 CompilationPhase phase("H_Block building", info_); |
1369 set_current_block(graph()->entry_block()); | 1372 set_current_block(graph()->entry_block()); |
1370 if (!BuildGraph()) return NULL; | 1373 if (!BuildGraph()) return NULL; |
1371 graph()->FinalizeUniqueness(); | 1374 graph()->FinalizeUniqueness(); |
1372 return graph_; | 1375 return graph_; |
1373 } | 1376 } |
1374 | 1377 |
1375 int HGraphBuilder::TraceInlinedFunction(Handle<SharedFunctionInfo> shared, | 1378 int HGraphBuilder::TraceInlinedFunction(Handle<SharedFunctionInfo> shared, |
1376 SourcePosition position) { | 1379 SourcePosition position) { |
1377 DCHECK(info_->is_tracking_positions()); | 1380 DCHECK(is_tracking_positions()); |
1378 | 1381 |
1379 int inline_id = static_cast<int>(graph()->inlined_function_infos().size()); | 1382 int inline_id = static_cast<int>(graph()->inlined_function_infos().size()); |
1380 HInlinedFunctionInfo info(shared->start_position()); | 1383 HInlinedFunctionInfo info(shared->start_position()); |
1381 if (!shared->script()->IsUndefined(isolate())) { | 1384 if (!shared->script()->IsUndefined(isolate())) { |
1382 Handle<Script> script(Script::cast(shared->script()), isolate()); | 1385 Handle<Script> script(Script::cast(shared->script()), isolate()); |
1383 | 1386 |
1384 if (FLAG_hydrogen_track_positions && | 1387 if (FLAG_hydrogen_track_positions && |
1385 !script->source()->IsUndefined(isolate())) { | 1388 !script->source()->IsUndefined(isolate())) { |
1386 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); | 1389 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); |
1387 Object* source_name = script->name(); | 1390 Object* source_name = script->name(); |
(...skipping 1971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3359 | 3362 |
3360 return Pop(); | 3363 return Pop(); |
3361 } | 3364 } |
3362 | 3365 |
3363 HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) { | 3366 HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) { |
3364 HValue* native_context = BuildGetNativeContext(); | 3367 HValue* native_context = BuildGetNativeContext(); |
3365 HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index); | 3368 HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index); |
3366 return Add<HLoadNamedField>(native_context, nullptr, function_access); | 3369 return Add<HLoadNamedField>(native_context, nullptr, function_access); |
3367 } | 3370 } |
3368 | 3371 |
3369 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) | 3372 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, |
3370 : HGraphBuilder(info, CallInterfaceDescriptor()), | 3373 bool track_positions) |
| 3374 : HGraphBuilder(info, CallInterfaceDescriptor(), track_positions), |
3371 function_state_(NULL), | 3375 function_state_(NULL), |
3372 initial_function_state_(this, info, NORMAL_RETURN, 0, | 3376 initial_function_state_(this, info, NORMAL_RETURN, 0, |
3373 TailCallMode::kAllow), | 3377 TailCallMode::kAllow), |
3374 ast_context_(NULL), | 3378 ast_context_(NULL), |
3375 break_scope_(NULL), | 3379 break_scope_(NULL), |
3376 inlined_count_(0), | 3380 inlined_count_(0), |
3377 globals_(10, info->zone()), | 3381 globals_(10, info->zone()), |
3378 osr_(new (info->zone()) HOsrBuilder(this)), | 3382 osr_(new (info->zone()) HOsrBuilder(this)), |
3379 bounds_(info->zone()) { | 3383 bounds_(info->zone()) { |
3380 // This is not initialized in the initializer list because the | 3384 // This is not initialized in the initializer list because the |
3381 // constructor for the initial state relies on function_state_ == NULL | 3385 // constructor for the initial state relies on function_state_ == NULL |
3382 // to know it's the initial state. | 3386 // to know it's the initial state. |
3383 function_state_ = &initial_function_state_; | 3387 function_state_ = &initial_function_state_; |
3384 InitializeAstVisitor(info->isolate()); | 3388 InitializeAstVisitor(info->isolate()); |
3385 if (top_info()->is_tracking_positions()) { | |
3386 SetSourcePosition(info->shared_info()->start_position()); | |
3387 } | |
3388 } | 3389 } |
3389 | 3390 |
3390 | 3391 |
3391 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, | 3392 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, |
3392 HBasicBlock* second, | 3393 HBasicBlock* second, |
3393 BailoutId join_id) { | 3394 BailoutId join_id) { |
3394 if (first == NULL) { | 3395 if (first == NULL) { |
3395 return second; | 3396 return second; |
3396 } else if (second == NULL) { | 3397 } else if (second == NULL) { |
3397 return first; | 3398 return first; |
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3944 function_return_ = owner->graph()->CreateBasicBlock(); | 3945 function_return_ = owner->graph()->CreateBasicBlock(); |
3945 function_return()->MarkAsInlineReturnTarget(owner->current_block()); | 3946 function_return()->MarkAsInlineReturnTarget(owner->current_block()); |
3946 } | 3947 } |
3947 // Set this after possibly allocating a new TestContext above. | 3948 // Set this after possibly allocating a new TestContext above. |
3948 call_context_ = owner->ast_context(); | 3949 call_context_ = owner->ast_context(); |
3949 } | 3950 } |
3950 | 3951 |
3951 // Push on the state stack. | 3952 // Push on the state stack. |
3952 owner->set_function_state(this); | 3953 owner->set_function_state(this); |
3953 | 3954 |
3954 if (compilation_info_->is_tracking_positions()) { | 3955 if (owner->is_tracking_positions()) { |
3955 outer_source_position_ = owner->source_position(); | 3956 outer_source_position_ = owner->source_position(); |
3956 owner->EnterInlinedSource( | 3957 owner->EnterInlinedSource( |
3957 info->shared_info()->start_position(), | 3958 info->shared_info()->start_position(), |
3958 inlining_id); | 3959 inlining_id); |
3959 owner->SetSourcePosition(info->shared_info()->start_position()); | 3960 owner->SetSourcePosition(info->shared_info()->start_position()); |
3960 } | 3961 } |
3961 } | 3962 } |
3962 | 3963 |
3963 | 3964 |
3964 FunctionState::~FunctionState() { | 3965 FunctionState::~FunctionState() { |
3965 delete test_context_; | 3966 delete test_context_; |
3966 owner_->set_function_state(outer_); | 3967 owner_->set_function_state(outer_); |
3967 | 3968 |
3968 if (compilation_info_->is_tracking_positions()) { | 3969 if (owner_->is_tracking_positions()) { |
3969 owner_->set_source_position(outer_source_position_); | 3970 owner_->set_source_position(outer_source_position_); |
3970 owner_->EnterInlinedSource( | 3971 owner_->EnterInlinedSource( |
3971 outer_->compilation_info()->shared_info()->start_position(), | 3972 outer_->compilation_info()->shared_info()->start_position(), |
3972 outer_->inlining_id()); | 3973 outer_->inlining_id()); |
3973 } | 3974 } |
3974 } | 3975 } |
3975 | 3976 |
3976 | 3977 |
3977 // Implementation of utility classes to represent an expression's context in | 3978 // Implementation of utility classes to represent an expression's context in |
3978 // the AST. | 3979 // the AST. |
(...skipping 3051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7030 DCHECK(current_block()->HasPredecessor()); | 7031 DCHECK(current_block()->HasPredecessor()); |
7031 if (!ast_context()->IsEffect()) { | 7032 if (!ast_context()->IsEffect()) { |
7032 // The parser turns invalid left-hand sides in assignments into throw | 7033 // The parser turns invalid left-hand sides in assignments into throw |
7033 // statements, which may not be in effect contexts. We might still try | 7034 // statements, which may not be in effect contexts. We might still try |
7034 // to optimize such functions; bail out now if we do. | 7035 // to optimize such functions; bail out now if we do. |
7035 return Bailout(kInvalidLeftHandSideInAssignment); | 7036 return Bailout(kInvalidLeftHandSideInAssignment); |
7036 } | 7037 } |
7037 CHECK_ALIVE(VisitForValue(expr->exception())); | 7038 CHECK_ALIVE(VisitForValue(expr->exception())); |
7038 | 7039 |
7039 HValue* value = environment()->Pop(); | 7040 HValue* value = environment()->Pop(); |
7040 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position()); | 7041 if (!is_tracking_positions()) SetSourcePosition(expr->position()); |
7041 Add<HPushArguments>(value); | 7042 Add<HPushArguments>(value); |
7042 Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kThrow), 1); | 7043 Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kThrow), 1); |
7043 Add<HSimulate>(expr->id()); | 7044 Add<HSimulate>(expr->id()); |
7044 | 7045 |
7045 // If the throw definitely exits the function, we can finish with a dummy | 7046 // If the throw definitely exits the function, we can finish with a dummy |
7046 // control flow at this point. This is not the case if the throw is inside | 7047 // control flow at this point. This is not the case if the throw is inside |
7047 // an inlined function which may be replaced. | 7048 // an inlined function which may be replaced. |
7048 if (call_context() == NULL) { | 7049 if (call_context() == NULL) { |
7049 FinishExitCurrentBlock(New<HAbnormalExit>()); | 7050 FinishExitCurrentBlock(New<HAbnormalExit>()); |
7050 } | 7051 } |
(...skipping 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8336 JSFunction::EnsureLiterals(target); | 8337 JSFunction::EnsureLiterals(target); |
8337 | 8338 |
8338 // Type-check the inlined function. | 8339 // Type-check the inlined function. |
8339 DCHECK(target_shared->has_deoptimization_support()); | 8340 DCHECK(target_shared->has_deoptimization_support()); |
8340 AstTyper(target_info.isolate(), target_info.zone(), target_info.closure(), | 8341 AstTyper(target_info.isolate(), target_info.zone(), target_info.closure(), |
8341 target_info.scope(), target_info.osr_ast_id(), target_info.literal(), | 8342 target_info.scope(), target_info.osr_ast_id(), target_info.literal(), |
8342 &bounds_) | 8343 &bounds_) |
8343 .Run(); | 8344 .Run(); |
8344 | 8345 |
8345 int inlining_id = 0; | 8346 int inlining_id = 0; |
8346 if (top_info()->is_tracking_positions()) { | 8347 if (is_tracking_positions()) { |
8347 inlining_id = TraceInlinedFunction(target_shared, source_position()); | 8348 inlining_id = TraceInlinedFunction(target_shared, source_position()); |
8348 } | 8349 } |
8349 | 8350 |
8350 // Save the pending call context. Set up new one for the inlined function. | 8351 // Save the pending call context. Set up new one for the inlined function. |
8351 // The function state is new-allocated because we need to delete it | 8352 // The function state is new-allocated because we need to delete it |
8352 // in two different places. | 8353 // in two different places. |
8353 FunctionState* target_state = new FunctionState( | 8354 FunctionState* target_state = new FunctionState( |
8354 this, &target_info, inlining_kind, inlining_id, | 8355 this, &target_info, inlining_kind, inlining_id, |
8355 function_state()->ComputeTailCallMode(syntactic_tail_call_mode)); | 8356 function_state()->ComputeTailCallMode(syntactic_tail_call_mode)); |
8356 | 8357 |
(...skipping 28 matching lines...) Expand all Loading... |
8385 // adopted. | 8386 // adopted. |
8386 Add<HSimulate>(BailoutId::None()); | 8387 Add<HSimulate>(BailoutId::None()); |
8387 | 8388 |
8388 current_block()->UpdateEnvironment(inner_env); | 8389 current_block()->UpdateEnvironment(inner_env); |
8389 Scope* saved_scope = scope(); | 8390 Scope* saved_scope = scope(); |
8390 set_scope(target_info.scope()); | 8391 set_scope(target_info.scope()); |
8391 HEnterInlined* enter_inlined = Add<HEnterInlined>( | 8392 HEnterInlined* enter_inlined = Add<HEnterInlined>( |
8392 return_id, target, context, arguments_count, function, | 8393 return_id, target, context, arguments_count, function, |
8393 function_state()->inlining_kind(), function->scope()->arguments(), | 8394 function_state()->inlining_kind(), function->scope()->arguments(), |
8394 arguments_object, syntactic_tail_call_mode); | 8395 arguments_object, syntactic_tail_call_mode); |
8395 if (top_info()->is_tracking_positions()) { | 8396 if (is_tracking_positions()) { |
8396 enter_inlined->set_inlining_id(inlining_id); | 8397 enter_inlined->set_inlining_id(inlining_id); |
8397 } | 8398 } |
8398 function_state()->set_entry(enter_inlined); | 8399 function_state()->set_entry(enter_inlined); |
8399 | 8400 |
8400 VisitDeclarations(target_info.scope()->declarations()); | 8401 VisitDeclarations(target_info.scope()->declarations()); |
8401 VisitStatements(function->body()); | 8402 VisitStatements(function->body()); |
8402 set_scope(saved_scope); | 8403 set_scope(saved_scope); |
8403 if (HasStackOverflow()) { | 8404 if (HasStackOverflow()) { |
8404 // Bail out if the inline function did, as we cannot residualize a call | 8405 // Bail out if the inline function did, as we cannot residualize a call |
8405 // instead, but do not disable optimization for the outer function. | 8406 // instead, but do not disable optimization for the outer function. |
(...skipping 1178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9584 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 9585 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
9585 DCHECK_NOT_NULL(current_info()->scope()->arguments()); | 9586 DCHECK_NOT_NULL(current_info()->scope()->arguments()); |
9586 return true; | 9587 return true; |
9587 } | 9588 } |
9588 | 9589 |
9589 | 9590 |
9590 void HOptimizedGraphBuilder::VisitCall(Call* expr) { | 9591 void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
9591 DCHECK(!HasStackOverflow()); | 9592 DCHECK(!HasStackOverflow()); |
9592 DCHECK(current_block() != NULL); | 9593 DCHECK(current_block() != NULL); |
9593 DCHECK(current_block()->HasPredecessor()); | 9594 DCHECK(current_block()->HasPredecessor()); |
9594 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position()); | 9595 if (!is_tracking_positions()) SetSourcePosition(expr->position()); |
9595 Expression* callee = expr->expression(); | 9596 Expression* callee = expr->expression(); |
9596 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 9597 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
9597 HInstruction* call = NULL; | 9598 HInstruction* call = NULL; |
9598 | 9599 |
9599 TailCallMode syntactic_tail_call_mode = expr->tail_call_mode(); | 9600 TailCallMode syntactic_tail_call_mode = expr->tail_call_mode(); |
9600 TailCallMode tail_call_mode = | 9601 TailCallMode tail_call_mode = |
9601 function_state()->ComputeTailCallMode(syntactic_tail_call_mode); | 9602 function_state()->ComputeTailCallMode(syntactic_tail_call_mode); |
9602 | 9603 |
9603 Property* prop = callee->AsProperty(); | 9604 Property* prop = callee->AsProperty(); |
9604 if (prop != NULL) { | 9605 if (prop != NULL) { |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9866 !IsSubclassConstructor(constructor->shared()->kind()) && | 9867 !IsSubclassConstructor(constructor->shared()->kind()) && |
9867 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 9868 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
9868 constructor->initial_map()->instance_size() < | 9869 constructor->initial_map()->instance_size() < |
9869 HAllocate::kMaxInlineSize; | 9870 HAllocate::kMaxInlineSize; |
9870 } | 9871 } |
9871 | 9872 |
9872 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 9873 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
9873 DCHECK(!HasStackOverflow()); | 9874 DCHECK(!HasStackOverflow()); |
9874 DCHECK(current_block() != NULL); | 9875 DCHECK(current_block() != NULL); |
9875 DCHECK(current_block()->HasPredecessor()); | 9876 DCHECK(current_block()->HasPredecessor()); |
9876 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position()); | 9877 if (!is_tracking_positions()) SetSourcePosition(expr->position()); |
9877 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 9878 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
9878 Factory* factory = isolate()->factory(); | 9879 Factory* factory = isolate()->factory(); |
9879 | 9880 |
9880 // The constructor function is on the stack in the unoptimized code | 9881 // The constructor function is on the stack in the unoptimized code |
9881 // during evaluation of the arguments. | 9882 // during evaluation of the arguments. |
9882 CHECK_ALIVE(VisitForValue(expr->expression())); | 9883 CHECK_ALIVE(VisitForValue(expr->expression())); |
9883 HValue* function = Top(); | 9884 HValue* function = Top(); |
9884 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 9885 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
9885 | 9886 |
9886 if (function->IsConstant() && | 9887 if (function->IsConstant() && |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10593 if (key != NULL) Push(key); | 10594 if (key != NULL) Push(key); |
10594 Push(value); | 10595 Push(value); |
10595 BuildStore(expr, prop, slot, ast_id, return_id); | 10596 BuildStore(expr, prop, slot, ast_id, return_id); |
10596 } | 10597 } |
10597 | 10598 |
10598 | 10599 |
10599 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 10600 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
10600 DCHECK(!HasStackOverflow()); | 10601 DCHECK(!HasStackOverflow()); |
10601 DCHECK(current_block() != NULL); | 10602 DCHECK(current_block() != NULL); |
10602 DCHECK(current_block()->HasPredecessor()); | 10603 DCHECK(current_block()->HasPredecessor()); |
10603 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position()); | 10604 if (!is_tracking_positions()) SetSourcePosition(expr->position()); |
10604 Expression* target = expr->expression(); | 10605 Expression* target = expr->expression(); |
10605 VariableProxy* proxy = target->AsVariableProxy(); | 10606 VariableProxy* proxy = target->AsVariableProxy(); |
10606 Property* prop = target->AsProperty(); | 10607 Property* prop = target->AsProperty(); |
10607 if (proxy == NULL && prop == NULL) { | 10608 if (proxy == NULL && prop == NULL) { |
10608 return Bailout(kInvalidLhsInCountOperation); | 10609 return Bailout(kInvalidLhsInCountOperation); |
10609 } | 10610 } |
10610 | 10611 |
10611 // Match the full code generator stack by simulating an extra stack | 10612 // Match the full code generator stack by simulating an extra stack |
10612 // element for postfix operations in a non-effect context. The return | 10613 // element for postfix operations in a non-effect context. The return |
10613 // value is ToNumber(input). | 10614 // value is ToNumber(input). |
(...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11309 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { | 11310 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { |
11310 CHECK_ALIVE(VisitForValue(expr->left())); | 11311 CHECK_ALIVE(VisitForValue(expr->left())); |
11311 CHECK_ALIVE(VisitForValue(expr->right())); | 11312 CHECK_ALIVE(VisitForValue(expr->right())); |
11312 SetSourcePosition(expr->position()); | 11313 SetSourcePosition(expr->position()); |
11313 HValue* right = Pop(); | 11314 HValue* right = Pop(); |
11314 HValue* left = Pop(); | 11315 HValue* left = Pop(); |
11315 HValue* result = | 11316 HValue* result = |
11316 BuildBinaryOperation(expr, left, right, | 11317 BuildBinaryOperation(expr, left, right, |
11317 ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE | 11318 ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE |
11318 : PUSH_BEFORE_SIMULATE); | 11319 : PUSH_BEFORE_SIMULATE); |
11319 if (top_info()->is_tracking_positions() && result->IsBinaryOperation()) { | 11320 if (is_tracking_positions() && result->IsBinaryOperation()) { |
11320 HBinaryOperation::cast(result)->SetOperandPositions( | 11321 HBinaryOperation::cast(result)->SetOperandPositions( |
11321 zone(), | 11322 zone(), |
11322 ScriptPositionToSourcePosition(expr->left()->position()), | 11323 ScriptPositionToSourcePosition(expr->left()->position()), |
11323 ScriptPositionToSourcePosition(expr->right()->position())); | 11324 ScriptPositionToSourcePosition(expr->right()->position())); |
11324 } | 11325 } |
11325 return ast_context()->ReturnValue(result); | 11326 return ast_context()->ReturnValue(result); |
11326 } | 11327 } |
11327 | 11328 |
11328 | 11329 |
11329 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 11330 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
(...skipping 21 matching lines...) Expand all Loading... |
11351 !HConstant::cast(right)->handle(isolate)->IsString())); | 11352 !HConstant::cast(right)->handle(isolate)->IsString())); |
11352 } | 11353 } |
11353 | 11354 |
11354 } // namespace | 11355 } // namespace |
11355 | 11356 |
11356 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 11357 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
11357 DCHECK(!HasStackOverflow()); | 11358 DCHECK(!HasStackOverflow()); |
11358 DCHECK(current_block() != NULL); | 11359 DCHECK(current_block() != NULL); |
11359 DCHECK(current_block()->HasPredecessor()); | 11360 DCHECK(current_block()->HasPredecessor()); |
11360 | 11361 |
11361 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position()); | 11362 if (!is_tracking_positions()) SetSourcePosition(expr->position()); |
11362 | 11363 |
11363 // Check for a few fast cases. The AST visiting behavior must be in sync | 11364 // Check for a few fast cases. The AST visiting behavior must be in sync |
11364 // with the full codegen: We don't push both left and right values onto | 11365 // with the full codegen: We don't push both left and right values onto |
11365 // the expression stack when one side is a special-case literal. | 11366 // the expression stack when one side is a special-case literal. |
11366 Expression* sub_expr = NULL; | 11367 Expression* sub_expr = NULL; |
11367 Handle<String> check; | 11368 Handle<String> check; |
11368 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { | 11369 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { |
11369 return HandleLiteralCompareTypeof(expr, sub_expr, check); | 11370 return HandleLiteralCompareTypeof(expr, sub_expr, check); |
11370 } | 11371 } |
11371 if (expr->IsLiteralCompareUndefined(&sub_expr)) { | 11372 if (expr->IsLiteralCompareUndefined(&sub_expr)) { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11494 return New<HBranch>(graph()->GetConstantTrue()); | 11495 return New<HBranch>(graph()->GetConstantTrue()); |
11495 } | 11496 } |
11496 // Can we get away with map check and not instance type check? | 11497 // Can we get away with map check and not instance type check? |
11497 HValue* operand_to_check = | 11498 HValue* operand_to_check = |
11498 left->block()->block_id() < right->block()->block_id() ? left : right; | 11499 left->block()->block_id() < right->block()->block_id() ? left : right; |
11499 if (combined_type->IsClass()) { | 11500 if (combined_type->IsClass()) { |
11500 Handle<Map> map = combined_type->AsClass()->Map(); | 11501 Handle<Map> map = combined_type->AsClass()->Map(); |
11501 AddCheckMap(operand_to_check, map); | 11502 AddCheckMap(operand_to_check, map); |
11502 HCompareObjectEqAndBranch* result = | 11503 HCompareObjectEqAndBranch* result = |
11503 New<HCompareObjectEqAndBranch>(left, right); | 11504 New<HCompareObjectEqAndBranch>(left, right); |
11504 if (top_info()->is_tracking_positions()) { | 11505 if (is_tracking_positions()) { |
11505 result->set_operand_position(zone(), 0, left_position); | 11506 result->set_operand_position(zone(), 0, left_position); |
11506 result->set_operand_position(zone(), 1, right_position); | 11507 result->set_operand_position(zone(), 1, right_position); |
11507 } | 11508 } |
11508 return result; | 11509 return result; |
11509 } else { | 11510 } else { |
11510 BuildCheckHeapObject(operand_to_check); | 11511 BuildCheckHeapObject(operand_to_check); |
11511 Add<HCheckInstanceType>(operand_to_check, | 11512 Add<HCheckInstanceType>(operand_to_check, |
11512 HCheckInstanceType::IS_JS_RECEIVER); | 11513 HCheckInstanceType::IS_JS_RECEIVER); |
11513 HCompareObjectEqAndBranch* result = | 11514 HCompareObjectEqAndBranch* result = |
11514 New<HCompareObjectEqAndBranch>(left, right); | 11515 New<HCompareObjectEqAndBranch>(left, right); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11637 AddSimulate(bailout_id, REMOVABLE_SIMULATE); | 11638 AddSimulate(bailout_id, REMOVABLE_SIMULATE); |
11638 } | 11639 } |
11639 } | 11640 } |
11640 // TODO(jkummerow): Can we make this more efficient? | 11641 // TODO(jkummerow): Can we make this more efficient? |
11641 HBranch* branch = New<HBranch>(result); | 11642 HBranch* branch = New<HBranch>(result); |
11642 return branch; | 11643 return branch; |
11643 } else { | 11644 } else { |
11644 HCompareNumericAndBranch* result = | 11645 HCompareNumericAndBranch* result = |
11645 New<HCompareNumericAndBranch>(left, right, op); | 11646 New<HCompareNumericAndBranch>(left, right, op); |
11646 result->set_observed_input_representation(left_rep, right_rep); | 11647 result->set_observed_input_representation(left_rep, right_rep); |
11647 if (top_info()->is_tracking_positions()) { | 11648 if (is_tracking_positions()) { |
11648 result->SetOperandPositions(zone(), left_position, right_position); | 11649 result->SetOperandPositions(zone(), left_position, right_position); |
11649 } | 11650 } |
11650 return result; | 11651 return result; |
11651 } | 11652 } |
11652 } | 11653 } |
11653 } | 11654 } |
11654 | 11655 |
11655 | 11656 |
11656 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 11657 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
11657 Expression* sub_expr, | 11658 Expression* sub_expr, |
11658 NilValue nil) { | 11659 NilValue nil) { |
11659 DCHECK(!HasStackOverflow()); | 11660 DCHECK(!HasStackOverflow()); |
11660 DCHECK(current_block() != NULL); | 11661 DCHECK(current_block() != NULL); |
11661 DCHECK(current_block()->HasPredecessor()); | 11662 DCHECK(current_block()->HasPredecessor()); |
11662 DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); | 11663 DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); |
11663 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position()); | 11664 if (!is_tracking_positions()) SetSourcePosition(expr->position()); |
11664 CHECK_ALIVE(VisitForValue(sub_expr)); | 11665 CHECK_ALIVE(VisitForValue(sub_expr)); |
11665 HValue* value = Pop(); | 11666 HValue* value = Pop(); |
11666 HControlInstruction* instr; | 11667 HControlInstruction* instr; |
11667 if (expr->op() == Token::EQ_STRICT) { | 11668 if (expr->op() == Token::EQ_STRICT) { |
11668 HConstant* nil_constant = nil == kNullValue | 11669 HConstant* nil_constant = nil == kNullValue |
11669 ? graph()->GetConstantNull() | 11670 ? graph()->GetConstantNull() |
11670 : graph()->GetConstantUndefined(); | 11671 : graph()->GetConstantUndefined(); |
11671 instr = New<HCompareObjectEqAndBranch>(value, nil_constant); | 11672 instr = New<HCompareObjectEqAndBranch>(value, nil_constant); |
11672 } else { | 11673 } else { |
11673 DCHECK_EQ(Token::EQ, expr->op()); | 11674 DCHECK_EQ(Token::EQ, expr->op()); |
(...skipping 1392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13066 } | 13067 } |
13067 | 13068 |
13068 { | 13069 { |
13069 Tag HIR_tag(this, "HIR"); | 13070 Tag HIR_tag(this, "HIR"); |
13070 for (HInstructionIterator it(current); !it.Done(); it.Advance()) { | 13071 for (HInstructionIterator it(current); !it.Done(); it.Advance()) { |
13071 HInstruction* instruction = it.Current(); | 13072 HInstruction* instruction = it.Current(); |
13072 int uses = instruction->UseCount(); | 13073 int uses = instruction->UseCount(); |
13073 PrintIndent(); | 13074 PrintIndent(); |
13074 std::ostringstream os; | 13075 std::ostringstream os; |
13075 os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction; | 13076 os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction; |
13076 if (graph->info()->is_tracking_positions() && | 13077 if (instruction->has_position() && instruction->position().raw() != 0) { |
13077 instruction->has_position() && instruction->position().raw() != 0) { | |
13078 const SourcePosition pos = instruction->position(); | 13078 const SourcePosition pos = instruction->position(); |
13079 os << " pos:"; | 13079 os << " pos:"; |
13080 if (pos.inlining_id() != 0) os << pos.inlining_id() << "_"; | 13080 if (pos.inlining_id() != 0) os << pos.inlining_id() << "_"; |
13081 os << pos.position(); | 13081 os << pos.position(); |
13082 } | 13082 } |
13083 os << " <|@\n"; | 13083 os << " <|@\n"; |
13084 trace_.Add(os.str().c_str()); | 13084 trace_.Add(os.str().c_str()); |
13085 } | 13085 } |
13086 } | 13086 } |
13087 | 13087 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13278 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13278 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13279 } | 13279 } |
13280 | 13280 |
13281 #ifdef DEBUG | 13281 #ifdef DEBUG |
13282 graph_->Verify(false); // No full verify. | 13282 graph_->Verify(false); // No full verify. |
13283 #endif | 13283 #endif |
13284 } | 13284 } |
13285 | 13285 |
13286 } // namespace internal | 13286 } // namespace internal |
13287 } // namespace v8 | 13287 } // namespace v8 |
OLD | NEW |