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 |