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 2449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2950 bool has_control = op->ControlInputCount() == 1; | 2960 bool has_control = op->ControlInputCount() == 1; |
2951 bool has_effect = op->EffectInputCount() == 1; | 2961 bool has_effect = op->EffectInputCount() == 1; |
2952 | 2962 |
2953 DCHECK(op->ControlInputCount() < 2); | 2963 DCHECK(op->ControlInputCount() < 2); |
2954 DCHECK(op->EffectInputCount() < 2); | 2964 DCHECK(op->EffectInputCount() < 2); |
2955 | 2965 |
2956 Node* result = NULL; | 2966 Node* result = NULL; |
2957 if (!has_context && !has_framestate && !has_control && !has_effect) { | 2967 if (!has_context && !has_framestate && !has_control && !has_effect) { |
2958 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); | 2968 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); |
2959 } else { | 2969 } else { |
| 2970 bool inside_try_scope = try_nesting_level_ > 0; |
2960 int input_count_with_deps = value_input_count; | 2971 int input_count_with_deps = value_input_count; |
2961 if (has_context) ++input_count_with_deps; | 2972 if (has_context) ++input_count_with_deps; |
2962 if (has_framestate) ++input_count_with_deps; | 2973 if (has_framestate) ++input_count_with_deps; |
2963 if (has_control) ++input_count_with_deps; | 2974 if (has_control) ++input_count_with_deps; |
2964 if (has_effect) ++input_count_with_deps; | 2975 if (has_effect) ++input_count_with_deps; |
2965 Node** buffer = EnsureInputBufferSize(input_count_with_deps); | 2976 Node** buffer = EnsureInputBufferSize(input_count_with_deps); |
2966 memcpy(buffer, value_inputs, kPointerSize * value_input_count); | 2977 memcpy(buffer, value_inputs, kPointerSize * value_input_count); |
2967 Node** current_input = buffer + value_input_count; | 2978 Node** current_input = buffer + value_input_count; |
2968 if (has_context) { | 2979 if (has_context) { |
2969 *current_input++ = current_context(); | 2980 *current_input++ = current_context(); |
2970 } | 2981 } |
2971 if (has_framestate) { | 2982 if (has_framestate) { |
2972 // The frame state will be inserted later. Here we misuse | 2983 // The frame state will be inserted later. Here we misuse |
2973 // the dead_control node as a sentinel to be later overwritten | 2984 // the dead_control node as a sentinel to be later overwritten |
2974 // with the real frame state. | 2985 // with the real frame state. |
2975 *current_input++ = dead_control(); | 2986 *current_input++ = dead_control(); |
2976 } | 2987 } |
2977 if (has_effect) { | 2988 if (has_effect) { |
2978 *current_input++ = environment_->GetEffectDependency(); | 2989 *current_input++ = environment_->GetEffectDependency(); |
2979 } | 2990 } |
2980 if (has_control) { | 2991 if (has_control) { |
2981 *current_input++ = environment_->GetControlDependency(); | 2992 *current_input++ = environment_->GetControlDependency(); |
2982 } | 2993 } |
2983 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); | 2994 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); |
2984 if (has_effect) { | 2995 if (has_effect) { |
2985 environment_->UpdateEffectDependency(result); | 2996 environment_->UpdateEffectDependency(result); |
2986 } | 2997 } |
2987 if (result->op()->ControlOutputCount() > 0 && | 2998 if (!environment()->IsMarkedAsUnreachable()) { |
2988 !environment()->IsMarkedAsUnreachable()) { | 2999 // Update the current control dependency for control-producing nodes. |
2989 environment_->UpdateControlDependency(result); | 3000 if (NodeProperties::IsControl(result)) { |
| 3001 environment_->UpdateControlDependency(result); |
| 3002 } |
| 3003 // Add implicit exception continuation for throwing nodes. |
| 3004 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) { |
| 3005 Node* on_exception = graph()->NewNode(common()->IfException(), result); |
| 3006 environment_->UpdateControlDependency(on_exception); |
| 3007 if (FLAG_turbo_exceptions) { |
| 3008 execution_control()->ThrowValue(jsgraph()->UndefinedConstant()); |
| 3009 } |
| 3010 } |
| 3011 // Add implicit success continuation for throwing nodes. |
| 3012 if (!result->op()->HasProperty(Operator::kNoThrow)) { |
| 3013 Node* on_success = graph()->NewNode(common()->IfSuccess(), result); |
| 3014 environment_->UpdateControlDependency(on_success); |
| 3015 } |
2990 } | 3016 } |
2991 } | 3017 } |
2992 | 3018 |
2993 return result; | 3019 return result; |
2994 } | 3020 } |
2995 | 3021 |
2996 | 3022 |
2997 void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | 3023 void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
2998 if (environment()->IsMarkedAsUnreachable()) return; | 3024 if (environment()->IsMarkedAsUnreachable()) return; |
2999 if (exit_control() != NULL) { | 3025 if (exit_control() != NULL) { |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3163 Node* dead_node = graph()->NewNode(common()->Dead()); | 3189 Node* dead_node = graph()->NewNode(common()->Dead()); |
3164 dead_control_.set(dead_node); | 3190 dead_control_.set(dead_node); |
3165 return dead_node; | 3191 return dead_node; |
3166 } | 3192 } |
3167 return dead_control_.get(); | 3193 return dead_control_.get(); |
3168 } | 3194 } |
3169 | 3195 |
3170 } // namespace compiler | 3196 } // namespace compiler |
3171 } // namespace internal | 3197 } // namespace internal |
3172 } // namespace v8 | 3198 } // namespace v8 |
OLD | NEW |