| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/compiler/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/compiler/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
| 9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
| 10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 private: | 320 private: |
| 321 BreakableStatement* target_; | 321 BreakableStatement* target_; |
| 322 LoopBuilder* control_; | 322 LoopBuilder* control_; |
| 323 }; | 323 }; |
| 324 | 324 |
| 325 | 325 |
| 326 // Control scope implementation for a TryCatchStatement. | 326 // Control scope implementation for a TryCatchStatement. |
| 327 class AstGraphBuilder::ControlScopeForCatch : public ControlScope { | 327 class AstGraphBuilder::ControlScopeForCatch : public ControlScope { |
| 328 public: | 328 public: |
| 329 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control) | 329 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control) |
| 330 : ControlScope(owner, 0), control_(control) {} | 330 : ControlScope(owner, 0), control_(control) { |
| 331 builder()->try_nesting_level_++; // Increment nesting. |
| 332 } |
| 333 ~ControlScopeForCatch() { |
| 334 builder()->try_nesting_level_--; // Decrement nesting. |
| 335 } |
| 331 | 336 |
| 332 protected: | 337 protected: |
| 333 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { | 338 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { |
| 334 switch (cmd) { | 339 switch (cmd) { |
| 335 case CMD_THROW: | 340 case CMD_THROW: |
| 336 control_->Throw(value); | 341 control_->Throw(value); |
| 337 return true; | 342 return true; |
| 338 case CMD_BREAK: | 343 case CMD_BREAK: |
| 339 case CMD_CONTINUE: | 344 case CMD_CONTINUE: |
| 340 case CMD_RETURN: | 345 case CMD_RETURN: |
| 341 break; | 346 break; |
| 342 } | 347 } |
| 343 return false; | 348 return false; |
| 344 } | 349 } |
| 345 | 350 |
| 346 private: | 351 private: |
| 347 TryCatchBuilder* control_; | 352 TryCatchBuilder* control_; |
| 348 }; | 353 }; |
| 349 | 354 |
| 350 | 355 |
| 351 // Control scope implementation for a TryFinallyStatement. | 356 // Control scope implementation for a TryFinallyStatement. |
| 352 class AstGraphBuilder::ControlScopeForFinally : public ControlScope { | 357 class AstGraphBuilder::ControlScopeForFinally : public ControlScope { |
| 353 public: | 358 public: |
| 354 ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands, | 359 ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands, |
| 355 TryFinallyBuilder* control) | 360 TryFinallyBuilder* control) |
| 356 : ControlScope(owner, 0), commands_(commands), control_(control) {} | 361 : ControlScope(owner, 0), commands_(commands), control_(control) { |
| 362 builder()->try_nesting_level_++; // Increment nesting. |
| 363 } |
| 364 ~ControlScopeForFinally() { |
| 365 builder()->try_nesting_level_--; // Decrement nesting. |
| 366 } |
| 357 | 367 |
| 358 protected: | 368 protected: |
| 359 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { | 369 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { |
| 360 Node* token = commands_->RecordCommand(cmd, target, value); | 370 Node* token = commands_->RecordCommand(cmd, target, value); |
| 361 control_->LeaveTry(token); | 371 control_->LeaveTry(token); |
| 362 return true; | 372 return true; |
| 363 } | 373 } |
| 364 | 374 |
| 365 private: | 375 private: |
| 366 DeferredCommands* commands_; | 376 DeferredCommands* commands_; |
| 367 TryFinallyBuilder* control_; | 377 TryFinallyBuilder* control_; |
| 368 }; | 378 }; |
| 369 | 379 |
| 370 | 380 |
| 371 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, | 381 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, |
| 372 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) | 382 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) |
| 373 : local_zone_(local_zone), | 383 : local_zone_(local_zone), |
| 374 info_(info), | 384 info_(info), |
| 375 jsgraph_(jsgraph), | 385 jsgraph_(jsgraph), |
| 376 environment_(nullptr), | 386 environment_(nullptr), |
| 377 ast_context_(nullptr), | 387 ast_context_(nullptr), |
| 378 globals_(0, local_zone), | 388 globals_(0, local_zone), |
| 379 execution_control_(nullptr), | 389 execution_control_(nullptr), |
| 380 execution_context_(nullptr), | 390 execution_context_(nullptr), |
| 391 try_nesting_level_(0), |
| 381 input_buffer_size_(0), | 392 input_buffer_size_(0), |
| 382 input_buffer_(nullptr), | 393 input_buffer_(nullptr), |
| 383 exit_control_(nullptr), | 394 exit_control_(nullptr), |
| 384 loop_assignment_analysis_(loop) { | 395 loop_assignment_analysis_(loop) { |
| 385 InitializeAstVisitor(info->isolate(), local_zone); | 396 InitializeAstVisitor(info->isolate(), local_zone); |
| 386 } | 397 } |
| 387 | 398 |
| 388 | 399 |
| 389 Node* AstGraphBuilder::GetFunctionClosure() { | 400 Node* AstGraphBuilder::GetFunctionClosure() { |
| 390 if (!function_closure_.is_set()) { | 401 if (!function_closure_.is_set()) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 if (FLAG_trace) { | 490 if (FLAG_trace) { |
| 480 // TODO(mstarzinger): Only traces implicit return. | 491 // TODO(mstarzinger): Only traces implicit return. |
| 481 Node* return_value = jsgraph()->UndefinedConstant(); | 492 Node* return_value = jsgraph()->UndefinedConstant(); |
| 482 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); | 493 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); |
| 483 } | 494 } |
| 484 | 495 |
| 485 // Return 'undefined' in case we can fall off the end. | 496 // Return 'undefined' in case we can fall off the end. |
| 486 BuildReturn(jsgraph()->UndefinedConstant()); | 497 BuildReturn(jsgraph()->UndefinedConstant()); |
| 487 | 498 |
| 488 // Finish the basic structure of the graph. | 499 // Finish the basic structure of the graph. |
| 489 environment()->UpdateControlDependency(exit_control()); | 500 graph()->SetEnd(graph()->NewNode(common()->End(), exit_control())); |
| 490 graph()->SetEnd(NewNode(common()->End())); | |
| 491 | 501 |
| 492 return true; | 502 return true; |
| 493 } | 503 } |
| 494 | 504 |
| 495 | 505 |
| 496 // Left-hand side can only be a property, a global or a variable slot. | 506 // Left-hand side can only be a property, a global or a variable slot. |
| 497 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 507 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 498 | 508 |
| 499 | 509 |
| 500 // Determine the left-hand side kind of an assignment. | 510 // Determine the left-hand side kind of an assignment. |
| (...skipping 2446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2947 bool has_control = op->ControlInputCount() == 1; | 2957 bool has_control = op->ControlInputCount() == 1; |
| 2948 bool has_effect = op->EffectInputCount() == 1; | 2958 bool has_effect = op->EffectInputCount() == 1; |
| 2949 | 2959 |
| 2950 DCHECK(op->ControlInputCount() < 2); | 2960 DCHECK(op->ControlInputCount() < 2); |
| 2951 DCHECK(op->EffectInputCount() < 2); | 2961 DCHECK(op->EffectInputCount() < 2); |
| 2952 | 2962 |
| 2953 Node* result = NULL; | 2963 Node* result = NULL; |
| 2954 if (!has_context && !has_framestate && !has_control && !has_effect) { | 2964 if (!has_context && !has_framestate && !has_control && !has_effect) { |
| 2955 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); | 2965 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); |
| 2956 } else { | 2966 } else { |
| 2967 bool inside_try_scope = try_nesting_level_ > 0; |
| 2957 int input_count_with_deps = value_input_count; | 2968 int input_count_with_deps = value_input_count; |
| 2958 if (has_context) ++input_count_with_deps; | 2969 if (has_context) ++input_count_with_deps; |
| 2959 if (has_framestate) ++input_count_with_deps; | 2970 if (has_framestate) ++input_count_with_deps; |
| 2960 if (has_control) ++input_count_with_deps; | 2971 if (has_control) ++input_count_with_deps; |
| 2961 if (has_effect) ++input_count_with_deps; | 2972 if (has_effect) ++input_count_with_deps; |
| 2962 Node** buffer = EnsureInputBufferSize(input_count_with_deps); | 2973 Node** buffer = EnsureInputBufferSize(input_count_with_deps); |
| 2963 memcpy(buffer, value_inputs, kPointerSize * value_input_count); | 2974 memcpy(buffer, value_inputs, kPointerSize * value_input_count); |
| 2964 Node** current_input = buffer + value_input_count; | 2975 Node** current_input = buffer + value_input_count; |
| 2965 if (has_context) { | 2976 if (has_context) { |
| 2966 *current_input++ = current_context(); | 2977 *current_input++ = current_context(); |
| 2967 } | 2978 } |
| 2968 if (has_framestate) { | 2979 if (has_framestate) { |
| 2969 // The frame state will be inserted later. Here we misuse | 2980 // The frame state will be inserted later. Here we misuse |
| 2970 // the {DeadControl} node as a sentinel to be later overwritten | 2981 // the {DeadControl} node as a sentinel to be later overwritten |
| 2971 // with the real frame state. | 2982 // with the real frame state. |
| 2972 *current_input++ = jsgraph()->DeadControl(); | 2983 *current_input++ = jsgraph()->DeadControl(); |
| 2973 } | 2984 } |
| 2974 if (has_effect) { | 2985 if (has_effect) { |
| 2975 *current_input++ = environment_->GetEffectDependency(); | 2986 *current_input++ = environment_->GetEffectDependency(); |
| 2976 } | 2987 } |
| 2977 if (has_control) { | 2988 if (has_control) { |
| 2978 *current_input++ = environment_->GetControlDependency(); | 2989 *current_input++ = environment_->GetControlDependency(); |
| 2979 } | 2990 } |
| 2980 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); | 2991 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); |
| 2981 if (has_effect) { | 2992 if (has_effect) { |
| 2982 environment_->UpdateEffectDependency(result); | 2993 environment_->UpdateEffectDependency(result); |
| 2983 } | 2994 } |
| 2984 if (result->op()->ControlOutputCount() > 0 && | 2995 if (!environment()->IsMarkedAsUnreachable()) { |
| 2985 !environment()->IsMarkedAsUnreachable()) { | 2996 // Update the current control dependency for control-producing nodes. |
| 2986 environment_->UpdateControlDependency(result); | 2997 if (NodeProperties::IsControl(result)) { |
| 2998 environment_->UpdateControlDependency(result); |
| 2999 } |
| 3000 // Add implicit exception continuation for throwing nodes. |
| 3001 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) { |
| 3002 Node* on_exception = graph()->NewNode(common()->IfException(), result); |
| 3003 environment_->UpdateControlDependency(on_exception); |
| 3004 if (FLAG_turbo_exceptions) { |
| 3005 execution_control()->ThrowValue(jsgraph()->UndefinedConstant()); |
| 3006 } |
| 3007 } |
| 3008 // Add implicit success continuation for throwing nodes. |
| 3009 if (!result->op()->HasProperty(Operator::kNoThrow)) { |
| 3010 Node* on_success = graph()->NewNode(common()->IfSuccess(), result); |
| 3011 environment_->UpdateControlDependency(on_success); |
| 3012 } |
| 2987 } | 3013 } |
| 2988 } | 3014 } |
| 2989 | 3015 |
| 2990 return result; | 3016 return result; |
| 2991 } | 3017 } |
| 2992 | 3018 |
| 2993 | 3019 |
| 2994 void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | 3020 void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
| 2995 if (environment()->IsMarkedAsUnreachable()) return; | 3021 if (environment()->IsMarkedAsUnreachable()) return; |
| 2996 if (exit_control() != NULL) { | 3022 if (exit_control() != NULL) { |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3150 // Phi does not exist yet, introduce one. | 3176 // Phi does not exist yet, introduce one. |
| 3151 value = NewPhi(inputs, value, control); | 3177 value = NewPhi(inputs, value, control); |
| 3152 value->ReplaceInput(inputs - 1, other); | 3178 value->ReplaceInput(inputs - 1, other); |
| 3153 } | 3179 } |
| 3154 return value; | 3180 return value; |
| 3155 } | 3181 } |
| 3156 | 3182 |
| 3157 } // namespace compiler | 3183 } // namespace compiler |
| 3158 } // namespace internal | 3184 } // namespace internal |
| 3159 } // namespace v8 | 3185 } // namespace v8 |
| OLD | NEW |