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 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, | 372 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, |
373 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) | 373 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) |
374 : local_zone_(local_zone), | 374 : local_zone_(local_zone), |
375 info_(info), | 375 info_(info), |
376 jsgraph_(jsgraph), | 376 jsgraph_(jsgraph), |
377 environment_(nullptr), | 377 environment_(nullptr), |
378 ast_context_(nullptr), | 378 ast_context_(nullptr), |
379 globals_(0, local_zone), | 379 globals_(0, local_zone), |
380 execution_control_(nullptr), | 380 execution_control_(nullptr), |
381 execution_context_(nullptr), | 381 execution_context_(nullptr), |
382 function_context_(nullptr), | |
383 input_buffer_size_(0), | 382 input_buffer_size_(0), |
384 input_buffer_(nullptr), | 383 input_buffer_(nullptr), |
385 exit_control_(nullptr), | 384 exit_control_(nullptr), |
386 loop_assignment_analysis_(loop) { | 385 loop_assignment_analysis_(loop) { |
387 InitializeAstVisitor(info->isolate(), local_zone); | 386 InitializeAstVisitor(info->isolate(), local_zone); |
388 } | 387 } |
389 | 388 |
390 | 389 |
391 Node* AstGraphBuilder::GetFunctionClosure() { | 390 Node* AstGraphBuilder::GetFunctionClosure() { |
392 if (!function_closure_.is_set()) { | 391 if (!function_closure_.is_set()) { |
393 const Operator* op = | 392 const Operator* op = |
394 common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex); | 393 common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex); |
395 Node* node = NewNode(op, graph()->start()); | 394 Node* node = NewNode(op, graph()->start()); |
396 function_closure_.set(node); | 395 function_closure_.set(node); |
397 } | 396 } |
398 return function_closure_.get(); | 397 return function_closure_.get(); |
399 } | 398 } |
400 | 399 |
401 | 400 |
402 Node* AstGraphBuilder::GetFunctionContext() { | 401 void AstGraphBuilder::CreateFunctionContext(bool constant_context) { |
403 DCHECK(function_context_ != nullptr); | 402 function_context_.set(constant_context |
404 return function_context_; | 403 ? jsgraph()->HeapConstant(info()->context()) |
| 404 : NewOuterContextParam()); |
405 } | 405 } |
406 | 406 |
407 | 407 |
408 Node* AstGraphBuilder::NewOuterContextParam() { | 408 Node* AstGraphBuilder::NewOuterContextParam() { |
409 // Parameter (arity + 1) is special for the outer context of the function | 409 // Parameter (arity + 1) is special for the outer context of the function |
410 const Operator* op = common()->Parameter(info()->num_parameters() + 1); | 410 const Operator* op = common()->Parameter(info()->num_parameters() + 1); |
411 return NewNode(op, graph()->start()); | 411 return NewNode(op, graph()->start()); |
412 } | 412 } |
413 | 413 |
414 | 414 |
415 Node* AstGraphBuilder::NewCurrentContextOsrValue() { | 415 Node* AstGraphBuilder::NewCurrentContextOsrValue() { |
416 // TODO(titzer): use a real OSR value here; a parameter works by accident. | 416 // TODO(titzer): use a real OSR value here; a parameter works by accident. |
417 // Parameter (arity + 1) is special for the outer context of the function | 417 // Parameter (arity + 1) is special for the outer context of the function |
418 const Operator* op = common()->Parameter(info()->num_parameters() + 1); | 418 const Operator* op = common()->Parameter(info()->num_parameters() + 1); |
419 return NewNode(op, graph()->start()); | 419 return NewNode(op, graph()->start()); |
420 } | 420 } |
421 | 421 |
422 | 422 |
423 bool AstGraphBuilder::CreateGraph() { | 423 bool AstGraphBuilder::CreateGraph(bool constant_context) { |
424 Scope* scope = info()->scope(); | 424 Scope* scope = info()->scope(); |
425 DCHECK(graph() != NULL); | 425 DCHECK(graph() != NULL); |
426 | 426 |
427 // Set up the basic structure of the graph. | 427 // Set up the basic structure of the graph. |
428 int parameter_count = info()->num_parameters(); | 428 int parameter_count = info()->num_parameters(); |
429 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); | 429 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); |
430 | 430 |
431 // Initialize control scope. | 431 // Initialize control scope. |
432 ControlScope control(this, 0); | 432 ControlScope control(this, 0); |
433 | 433 |
434 // Initialize the top-level environment. | 434 // Initialize the top-level environment. |
435 Environment env(this, scope, graph()->start()); | 435 Environment env(this, scope, graph()->start()); |
436 set_environment(&env); | 436 set_environment(&env); |
437 | 437 |
438 if (info()->is_osr()) { | 438 if (info()->is_osr()) { |
439 // Use OSR normal entry as the start of the top-level environment. | 439 // Use OSR normal entry as the start of the top-level environment. |
440 // It will be replaced with {Dead} after typing and optimizations. | 440 // It will be replaced with {Dead} after typing and optimizations. |
441 NewNode(common()->OsrNormalEntry()); | 441 NewNode(common()->OsrNormalEntry()); |
442 } | 442 } |
443 | 443 |
444 // Initialize the incoming context. | 444 // Initialize the incoming context. |
445 function_context_ = NewOuterContextParam(); | 445 CreateFunctionContext(constant_context); |
446 ContextScope incoming(this, scope, function_context_); | 446 ContextScope incoming(this, scope, function_context_.get()); |
447 | 447 |
448 // Build receiver check for sloppy mode if necessary. | 448 // Build receiver check for sloppy mode if necessary. |
449 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? | 449 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? |
450 Node* original_receiver = env.Lookup(scope->receiver()); | 450 Node* original_receiver = env.Lookup(scope->receiver()); |
451 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); | 451 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); |
452 env.Bind(scope->receiver(), patched_receiver); | 452 env.Bind(scope->receiver(), patched_receiver); |
453 | 453 |
454 // Build function context only if there are context allocated variables. | 454 // Build function context only if there are context allocated variables. |
455 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 455 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
456 if (heap_slots > 0) { | 456 if (heap_slots > 0) { |
457 // Push a new inner context scope for the function. | 457 // Push a new inner context scope for the function. |
458 Node* closure = GetFunctionClosure(); | 458 Node* closure = GetFunctionClosure(); |
459 Node* inner_context = BuildLocalFunctionContext(function_context_, closure); | 459 Node* inner_context = |
| 460 BuildLocalFunctionContext(function_context_.get(), closure); |
460 ContextScope top_context(this, scope, inner_context); | 461 ContextScope top_context(this, scope, inner_context); |
461 CreateGraphBody(); | 462 CreateGraphBody(); |
462 } else { | 463 } else { |
463 // Simply use the outer function context in building the graph. | 464 // Simply use the outer function context in building the graph. |
464 CreateGraphBody(); | 465 CreateGraphBody(); |
465 } | 466 } |
466 | 467 |
467 // Finish the basic structure of the graph. | 468 // Finish the basic structure of the graph. |
468 graph()->SetEnd(graph()->NewNode(common()->End(), exit_control())); | 469 graph()->SetEnd(graph()->NewNode(common()->End(), exit_control())); |
469 | 470 |
(...skipping 2283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2753 | 2754 |
2754 Node* AstGraphBuilder::BuildLoadBuiltinsObject() { | 2755 Node* AstGraphBuilder::BuildLoadBuiltinsObject() { |
2755 Node* global = BuildLoadGlobalObject(); | 2756 Node* global = BuildLoadGlobalObject(); |
2756 Node* builtins = | 2757 Node* builtins = |
2757 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset); | 2758 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset); |
2758 return builtins; | 2759 return builtins; |
2759 } | 2760 } |
2760 | 2761 |
2761 | 2762 |
2762 Node* AstGraphBuilder::BuildLoadGlobalObject() { | 2763 Node* AstGraphBuilder::BuildLoadGlobalObject() { |
2763 Node* context = GetFunctionContext(); | |
2764 const Operator* load_op = | 2764 const Operator* load_op = |
2765 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true); | 2765 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true); |
2766 return NewNode(load_op, context); | 2766 return NewNode(load_op, function_context_.get()); |
2767 } | 2767 } |
2768 | 2768 |
2769 | 2769 |
2770 Node* AstGraphBuilder::BuildLoadGlobalProxy() { | 2770 Node* AstGraphBuilder::BuildLoadGlobalProxy() { |
2771 Node* global = BuildLoadGlobalObject(); | 2771 Node* global = BuildLoadGlobalObject(); |
2772 Node* proxy = | 2772 Node* proxy = |
2773 BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset); | 2773 BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset); |
2774 return proxy; | 2774 return proxy; |
2775 } | 2775 } |
2776 | 2776 |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3016 if (exit_control() != NULL) { | 3016 if (exit_control() != NULL) { |
3017 exit = MergeControl(exit_control(), exit); | 3017 exit = MergeControl(exit_control(), exit); |
3018 } | 3018 } |
3019 environment()->MarkAsUnreachable(); | 3019 environment()->MarkAsUnreachable(); |
3020 set_exit_control(exit); | 3020 set_exit_control(exit); |
3021 } | 3021 } |
3022 | 3022 |
3023 | 3023 |
3024 void AstGraphBuilder::Environment::Merge(Environment* other) { | 3024 void AstGraphBuilder::Environment::Merge(Environment* other) { |
3025 DCHECK(values_.size() == other->values_.size()); | 3025 DCHECK(values_.size() == other->values_.size()); |
| 3026 // TODO(titzer): make context stack heights match. |
3026 DCHECK(contexts_.size() <= other->contexts_.size()); | 3027 DCHECK(contexts_.size() <= other->contexts_.size()); |
3027 | 3028 |
3028 // Nothing to do if the other environment is dead. | 3029 // Nothing to do if the other environment is dead. |
3029 if (other->IsMarkedAsUnreachable()) return; | 3030 if (other->IsMarkedAsUnreachable()) return; |
3030 | 3031 |
3031 // Resurrect a dead environment by copying the contents of the other one and | 3032 // Resurrect a dead environment by copying the contents of the other one and |
3032 // placing a singleton merge as the new control dependency. | 3033 // placing a singleton merge as the new control dependency. |
3033 if (this->IsMarkedAsUnreachable()) { | 3034 if (this->IsMarkedAsUnreachable()) { |
3034 Node* other_control = other->control_dependency_; | 3035 Node* other_control = other->control_dependency_; |
3035 Node* inputs[] = {other_control}; | 3036 Node* inputs[] = {other_control}; |
3036 control_dependency_ = | 3037 control_dependency_ = |
3037 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true); | 3038 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true); |
3038 effect_dependency_ = other->effect_dependency_; | 3039 effect_dependency_ = other->effect_dependency_; |
3039 values_ = other->values_; | 3040 values_ = other->values_; |
| 3041 // TODO(titzer): make context stack heights match. |
| 3042 size_t min = std::min(contexts_.size(), other->contexts_.size()); |
| 3043 contexts_ = other->contexts_; |
| 3044 contexts_.resize(min, nullptr); |
3040 return; | 3045 return; |
3041 } | 3046 } |
3042 | 3047 |
3043 // Create a merge of the control dependencies of both environments and update | 3048 // Create a merge of the control dependencies of both environments and update |
3044 // the current environment's control dependency accordingly. | 3049 // the current environment's control dependency accordingly. |
3045 Node* control = builder_->MergeControl(this->GetControlDependency(), | 3050 Node* control = builder_->MergeControl(this->GetControlDependency(), |
3046 other->GetControlDependency()); | 3051 other->GetControlDependency()); |
3047 UpdateControlDependency(control); | 3052 UpdateControlDependency(control); |
3048 | 3053 |
3049 // Create a merge of the effect dependencies of both environments and update | 3054 // Create a merge of the effect dependencies of both environments and update |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3203 // Phi does not exist yet, introduce one. | 3208 // Phi does not exist yet, introduce one. |
3204 value = NewPhi(inputs, value, control); | 3209 value = NewPhi(inputs, value, control); |
3205 value->ReplaceInput(inputs - 1, other); | 3210 value->ReplaceInput(inputs - 1, other); |
3206 } | 3211 } |
3207 return value; | 3212 return value; |
3208 } | 3213 } |
3209 | 3214 |
3210 } // namespace compiler | 3215 } // namespace compiler |
3211 } // namespace internal | 3216 } // namespace internal |
3212 } // namespace v8 | 3217 } // namespace v8 |
OLD | NEW |