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 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 private: | 321 private: |
322 BreakableStatement* target_; | 322 BreakableStatement* target_; |
323 LoopBuilder* control_; | 323 LoopBuilder* control_; |
324 }; | 324 }; |
325 | 325 |
326 | 326 |
327 // Control scope implementation for a TryCatchStatement. | 327 // Control scope implementation for a TryCatchStatement. |
328 class AstGraphBuilder::ControlScopeForCatch : public ControlScope { | 328 class AstGraphBuilder::ControlScopeForCatch : public ControlScope { |
329 public: | 329 public: |
330 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control) | 330 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control) |
331 : ControlScope(owner, 0), control_(control) {} | 331 : ControlScope(owner, 0), control_(control) { |
| 332 builder()->try_nesting_level_++; // Increment nesting. |
| 333 } |
| 334 ~ControlScopeForCatch() { |
| 335 builder()->try_nesting_level_--; // Decrement nesting. |
| 336 } |
332 | 337 |
333 protected: | 338 protected: |
334 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { | 339 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { |
335 switch (cmd) { | 340 switch (cmd) { |
336 case CMD_THROW: | 341 case CMD_THROW: |
337 control_->Throw(value); | 342 control_->Throw(value); |
338 return true; | 343 return true; |
339 case CMD_BREAK: | 344 case CMD_BREAK: |
340 case CMD_CONTINUE: | 345 case CMD_CONTINUE: |
341 case CMD_RETURN: | 346 case CMD_RETURN: |
342 break; | 347 break; |
343 } | 348 } |
344 return false; | 349 return false; |
345 } | 350 } |
346 | 351 |
347 private: | 352 private: |
348 TryCatchBuilder* control_; | 353 TryCatchBuilder* control_; |
349 }; | 354 }; |
350 | 355 |
351 | 356 |
352 // Control scope implementation for a TryFinallyStatement. | 357 // Control scope implementation for a TryFinallyStatement. |
353 class AstGraphBuilder::ControlScopeForFinally : public ControlScope { | 358 class AstGraphBuilder::ControlScopeForFinally : public ControlScope { |
354 public: | 359 public: |
355 ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands, | 360 ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands, |
356 TryFinallyBuilder* control) | 361 TryFinallyBuilder* control) |
357 : ControlScope(owner, 0), commands_(commands), control_(control) {} | 362 : ControlScope(owner, 0), commands_(commands), control_(control) { |
| 363 builder()->try_nesting_level_++; // Increment nesting. |
| 364 } |
| 365 ~ControlScopeForFinally() { |
| 366 builder()->try_nesting_level_--; // Decrement nesting. |
| 367 } |
358 | 368 |
359 protected: | 369 protected: |
360 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { | 370 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { |
361 Node* token = commands_->RecordCommand(cmd, target, value); | 371 Node* token = commands_->RecordCommand(cmd, target, value); |
362 control_->LeaveTry(token); | 372 control_->LeaveTry(token); |
363 return true; | 373 return true; |
364 } | 374 } |
365 | 375 |
366 private: | 376 private: |
367 DeferredCommands* commands_; | 377 DeferredCommands* commands_; |
368 TryFinallyBuilder* control_; | 378 TryFinallyBuilder* control_; |
369 }; | 379 }; |
370 | 380 |
371 | 381 |
372 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, | 382 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, |
373 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) | 383 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) |
374 : local_zone_(local_zone), | 384 : local_zone_(local_zone), |
375 info_(info), | 385 info_(info), |
376 jsgraph_(jsgraph), | 386 jsgraph_(jsgraph), |
377 environment_(nullptr), | 387 environment_(nullptr), |
378 ast_context_(nullptr), | 388 ast_context_(nullptr), |
379 globals_(0, local_zone), | 389 globals_(0, local_zone), |
380 execution_control_(nullptr), | 390 execution_control_(nullptr), |
381 execution_context_(nullptr), | 391 execution_context_(nullptr), |
| 392 try_nesting_level_(0), |
382 input_buffer_size_(0), | 393 input_buffer_size_(0), |
383 input_buffer_(nullptr), | 394 input_buffer_(nullptr), |
384 exit_control_(nullptr), | 395 exit_control_(nullptr), |
385 loop_assignment_analysis_(loop) { | 396 loop_assignment_analysis_(loop) { |
386 InitializeAstVisitor(info->isolate(), local_zone); | 397 InitializeAstVisitor(info->isolate(), local_zone); |
387 } | 398 } |
388 | 399 |
389 | 400 |
390 Node* AstGraphBuilder::GetFunctionClosure() { | 401 Node* AstGraphBuilder::GetFunctionClosure() { |
391 if (!function_closure_.is_set()) { | 402 if (!function_closure_.is_set()) { |
(...skipping 2575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2967 bool has_control = op->ControlInputCount() == 1; | 2978 bool has_control = op->ControlInputCount() == 1; |
2968 bool has_effect = op->EffectInputCount() == 1; | 2979 bool has_effect = op->EffectInputCount() == 1; |
2969 | 2980 |
2970 DCHECK(op->ControlInputCount() < 2); | 2981 DCHECK(op->ControlInputCount() < 2); |
2971 DCHECK(op->EffectInputCount() < 2); | 2982 DCHECK(op->EffectInputCount() < 2); |
2972 | 2983 |
2973 Node* result = NULL; | 2984 Node* result = NULL; |
2974 if (!has_context && !has_framestate && !has_control && !has_effect) { | 2985 if (!has_context && !has_framestate && !has_control && !has_effect) { |
2975 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); | 2986 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); |
2976 } else { | 2987 } else { |
| 2988 bool inside_try_scope = try_nesting_level_ > 0; |
2977 int input_count_with_deps = value_input_count; | 2989 int input_count_with_deps = value_input_count; |
2978 if (has_context) ++input_count_with_deps; | 2990 if (has_context) ++input_count_with_deps; |
2979 if (has_framestate) ++input_count_with_deps; | 2991 if (has_framestate) ++input_count_with_deps; |
2980 if (has_control) ++input_count_with_deps; | 2992 if (has_control) ++input_count_with_deps; |
2981 if (has_effect) ++input_count_with_deps; | 2993 if (has_effect) ++input_count_with_deps; |
2982 Node** buffer = EnsureInputBufferSize(input_count_with_deps); | 2994 Node** buffer = EnsureInputBufferSize(input_count_with_deps); |
2983 memcpy(buffer, value_inputs, kPointerSize * value_input_count); | 2995 memcpy(buffer, value_inputs, kPointerSize * value_input_count); |
2984 Node** current_input = buffer + value_input_count; | 2996 Node** current_input = buffer + value_input_count; |
2985 if (has_context) { | 2997 if (has_context) { |
2986 *current_input++ = current_context(); | 2998 *current_input++ = current_context(); |
2987 } | 2999 } |
2988 if (has_framestate) { | 3000 if (has_framestate) { |
2989 // The frame state will be inserted later. Here we misuse | 3001 // The frame state will be inserted later. Here we misuse |
2990 // the {DeadControl} node as a sentinel to be later overwritten | 3002 // the {DeadControl} node as a sentinel to be later overwritten |
2991 // with the real frame state. | 3003 // with the real frame state. |
2992 *current_input++ = jsgraph()->DeadControl(); | 3004 *current_input++ = jsgraph()->DeadControl(); |
2993 } | 3005 } |
2994 if (has_effect) { | 3006 if (has_effect) { |
2995 *current_input++ = environment_->GetEffectDependency(); | 3007 *current_input++ = environment_->GetEffectDependency(); |
2996 } | 3008 } |
2997 if (has_control) { | 3009 if (has_control) { |
2998 *current_input++ = environment_->GetControlDependency(); | 3010 *current_input++ = environment_->GetControlDependency(); |
2999 } | 3011 } |
3000 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); | 3012 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); |
3001 if (has_effect) { | 3013 if (has_effect) { |
3002 environment_->UpdateEffectDependency(result); | 3014 environment_->UpdateEffectDependency(result); |
3003 } | 3015 } |
3004 if (result->op()->ControlOutputCount() > 0 && | 3016 if (!environment()->IsMarkedAsUnreachable()) { |
3005 !environment()->IsMarkedAsUnreachable()) { | 3017 // Update the current control dependency for control-producing nodes. |
3006 environment_->UpdateControlDependency(result); | 3018 if (NodeProperties::IsControl(result)) { |
| 3019 environment_->UpdateControlDependency(result); |
| 3020 } |
| 3021 // Add implicit exception continuation for throwing nodes. |
| 3022 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) { |
| 3023 Node* on_exception = graph()->NewNode(common()->IfException(), result); |
| 3024 environment_->UpdateControlDependency(on_exception); |
| 3025 if (FLAG_turbo_exceptions) { |
| 3026 execution_control()->ThrowValue(jsgraph()->UndefinedConstant()); |
| 3027 } |
| 3028 } |
| 3029 // Add implicit success continuation for throwing nodes. |
| 3030 if (!result->op()->HasProperty(Operator::kNoThrow)) { |
| 3031 Node* on_success = graph()->NewNode(common()->IfSuccess(), result); |
| 3032 environment_->UpdateControlDependency(on_success); |
| 3033 } |
3007 } | 3034 } |
3008 } | 3035 } |
3009 | 3036 |
3010 return result; | 3037 return result; |
3011 } | 3038 } |
3012 | 3039 |
3013 | 3040 |
3014 void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | 3041 void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
3015 if (environment()->IsMarkedAsUnreachable()) return; | 3042 if (environment()->IsMarkedAsUnreachable()) return; |
3016 if (exit_control() != NULL) { | 3043 if (exit_control() != NULL) { |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3208 // Phi does not exist yet, introduce one. | 3235 // Phi does not exist yet, introduce one. |
3209 value = NewPhi(inputs, value, control); | 3236 value = NewPhi(inputs, value, control); |
3210 value->ReplaceInput(inputs - 1, other); | 3237 value->ReplaceInput(inputs - 1, other); |
3211 } | 3238 } |
3212 return value; | 3239 return value; |
3213 } | 3240 } |
3214 | 3241 |
3215 } // namespace compiler | 3242 } // namespace compiler |
3216 } // namespace internal | 3243 } // namespace internal |
3217 } // namespace v8 | 3244 } // namespace v8 |
OLD | NEW |