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/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
9 #include "src/compiler/ast-loop-assignment-analyzer.h" | 9 #include "src/compiler/ast-loop-assignment-analyzer.h" |
10 #include "src/compiler/control-builders.h" | 10 #include "src/compiler/control-builders.h" |
(...skipping 2320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2331 BuildVariableLoad(proxy->var(), expr->expression()->id(), states, | 2331 BuildVariableLoad(proxy->var(), expr->expression()->id(), states, |
2332 pair, OutputFrameStateCombine::Push()); | 2332 pair, OutputFrameStateCombine::Push()); |
2333 receiver_hint = ConvertReceiverMode::kNullOrUndefined; | 2333 receiver_hint = ConvertReceiverMode::kNullOrUndefined; |
2334 receiver_value = jsgraph()->UndefinedConstant(); | 2334 receiver_value = jsgraph()->UndefinedConstant(); |
2335 break; | 2335 break; |
2336 } | 2336 } |
2337 case Call::LOOKUP_SLOT_CALL: { | 2337 case Call::LOOKUP_SLOT_CALL: { |
2338 Variable* variable = callee->AsVariableProxy()->var(); | 2338 Variable* variable = callee->AsVariableProxy()->var(); |
2339 DCHECK(variable->location() == VariableLocation::LOOKUP); | 2339 DCHECK(variable->location() == VariableLocation::LOOKUP); |
2340 Node* name = jsgraph()->Constant(variable->name()); | 2340 Node* name = jsgraph()->Constant(variable->name()); |
2341 const Operator* op = javascript()->CallRuntime(Runtime::kLoadLookupSlot); | 2341 const Operator* op = |
2342 Node* pair = NewNode(op, current_context(), name); | 2342 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall); |
| 2343 Node* pair = NewNode(op, name); |
2343 callee_value = NewNode(common()->Projection(0), pair); | 2344 callee_value = NewNode(common()->Projection(0), pair); |
2344 receiver_value = NewNode(common()->Projection(1), pair); | 2345 receiver_value = NewNode(common()->Projection(1), pair); |
2345 PrepareFrameState(pair, expr->LookupId(), | 2346 PrepareFrameState(pair, expr->LookupId(), |
2346 OutputFrameStateCombine::Push(2)); | 2347 OutputFrameStateCombine::Push(2)); |
2347 break; | 2348 break; |
2348 } | 2349 } |
2349 case Call::NAMED_PROPERTY_CALL: { | 2350 case Call::NAMED_PROPERTY_CALL: { |
2350 Property* property = callee->AsProperty(); | 2351 Property* property = callee->AsProperty(); |
2351 VectorSlotPair feedback = | 2352 VectorSlotPair feedback = |
2352 CreateVectorSlotPair(property->PropertyFeedbackSlot()); | 2353 CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2427 break; | 2428 break; |
2428 } | 2429 } |
2429 case Call::SUPER_CALL: | 2430 case Call::SUPER_CALL: |
2430 return VisitCallSuper(expr); | 2431 return VisitCallSuper(expr); |
2431 case Call::POSSIBLY_EVAL_CALL: | 2432 case Call::POSSIBLY_EVAL_CALL: |
2432 possibly_eval = true; | 2433 possibly_eval = true; |
2433 if (callee->AsVariableProxy()->var()->IsLookupSlot()) { | 2434 if (callee->AsVariableProxy()->var()->IsLookupSlot()) { |
2434 Variable* variable = callee->AsVariableProxy()->var(); | 2435 Variable* variable = callee->AsVariableProxy()->var(); |
2435 Node* name = jsgraph()->Constant(variable->name()); | 2436 Node* name = jsgraph()->Constant(variable->name()); |
2436 const Operator* op = | 2437 const Operator* op = |
2437 javascript()->CallRuntime(Runtime::kLoadLookupSlot); | 2438 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall); |
2438 Node* pair = NewNode(op, current_context(), name); | 2439 Node* pair = NewNode(op, name); |
2439 callee_value = NewNode(common()->Projection(0), pair); | 2440 callee_value = NewNode(common()->Projection(0), pair); |
2440 receiver_value = NewNode(common()->Projection(1), pair); | 2441 receiver_value = NewNode(common()->Projection(1), pair); |
2441 PrepareFrameState(pair, expr->LookupId(), | 2442 PrepareFrameState(pair, expr->LookupId(), |
2442 OutputFrameStateCombine::Push(2)); | 2443 OutputFrameStateCombine::Push(2)); |
2443 break; | 2444 break; |
2444 } | 2445 } |
2445 // Fall through. | 2446 // Fall through. |
2446 case Call::OTHER_CALL: | 2447 case Call::OTHER_CALL: |
2447 VisitForValue(callee); | 2448 VisitForValue(callee); |
2448 callee_value = environment()->Pop(); | 2449 callee_value = environment()->Pop(); |
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3395 return value; | 3396 return value; |
3396 } | 3397 } |
3397 case VariableLocation::LOOKUP: { | 3398 case VariableLocation::LOOKUP: { |
3398 // Dynamic lookup of context variable (anywhere in the chain). | 3399 // Dynamic lookup of context variable (anywhere in the chain). |
3399 Handle<String> name = variable->name(); | 3400 Handle<String> name = variable->name(); |
3400 if (Node* node = | 3401 if (Node* node = |
3401 TryLoadDynamicVariable(variable, name, bailout_id, states, | 3402 TryLoadDynamicVariable(variable, name, bailout_id, states, |
3402 feedback, combine, typeof_mode)) { | 3403 feedback, combine, typeof_mode)) { |
3403 return node; | 3404 return node; |
3404 } | 3405 } |
3405 const Operator* op = javascript()->LoadDynamic(name, typeof_mode); | 3406 Node* value = BuildDynamicLoad(name, typeof_mode); |
3406 Node* value = NewNode(op, BuildLoadFeedbackVector(), current_context()); | |
3407 states.AddToNode(value, bailout_id, combine); | 3407 states.AddToNode(value, bailout_id, combine); |
3408 return value; | 3408 return value; |
3409 } | 3409 } |
3410 } | 3410 } |
3411 UNREACHABLE(); | 3411 UNREACHABLE(); |
3412 return nullptr; | 3412 return nullptr; |
3413 } | 3413 } |
3414 | 3414 |
3415 | 3415 |
3416 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, | 3416 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, |
(...skipping 14 matching lines...) Expand all Loading... |
3431 case VariableLocation::LOCAL: | 3431 case VariableLocation::LOCAL: |
3432 case VariableLocation::CONTEXT: { | 3432 case VariableLocation::CONTEXT: { |
3433 // Local var, const, or let variable or context variable. | 3433 // Local var, const, or let variable or context variable. |
3434 return jsgraph()->BooleanConstant(variable->HasThisName(isolate())); | 3434 return jsgraph()->BooleanConstant(variable->HasThisName(isolate())); |
3435 } | 3435 } |
3436 case VariableLocation::LOOKUP: { | 3436 case VariableLocation::LOOKUP: { |
3437 // Dynamic lookup of context variable (anywhere in the chain). | 3437 // Dynamic lookup of context variable (anywhere in the chain). |
3438 Node* name = jsgraph()->Constant(variable->name()); | 3438 Node* name = jsgraph()->Constant(variable->name()); |
3439 const Operator* op = | 3439 const Operator* op = |
3440 javascript()->CallRuntime(Runtime::kDeleteLookupSlot); | 3440 javascript()->CallRuntime(Runtime::kDeleteLookupSlot); |
3441 Node* result = NewNode(op, current_context(), name); | 3441 Node* result = NewNode(op, name); |
3442 PrepareFrameState(result, bailout_id, combine); | 3442 PrepareFrameState(result, bailout_id, combine); |
3443 return result; | 3443 return result; |
3444 } | 3444 } |
3445 } | 3445 } |
3446 UNREACHABLE(); | 3446 UNREACHABLE(); |
3447 return nullptr; | 3447 return nullptr; |
3448 } | 3448 } |
3449 | 3449 |
3450 | 3450 |
3451 Node* AstGraphBuilder::BuildVariableAssignment( | 3451 Node* AstGraphBuilder::BuildVariableAssignment( |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3553 javascript()->LoadContext(depth, variable->index(), false); | 3553 javascript()->LoadContext(depth, variable->index(), false); |
3554 Node* current = NewNode(op, current_context()); | 3554 Node* current = NewNode(op, current_context()); |
3555 BuildHoleCheckThenThrow(current, variable, value, bailout_id); | 3555 BuildHoleCheckThenThrow(current, variable, value, bailout_id); |
3556 return BuildThrowConstAssignError(bailout_id); | 3556 return BuildThrowConstAssignError(bailout_id); |
3557 } | 3557 } |
3558 const Operator* op = javascript()->StoreContext(depth, variable->index()); | 3558 const Operator* op = javascript()->StoreContext(depth, variable->index()); |
3559 return NewNode(op, current_context(), value); | 3559 return NewNode(op, current_context(), value); |
3560 } | 3560 } |
3561 case VariableLocation::LOOKUP: { | 3561 case VariableLocation::LOOKUP: { |
3562 // Dynamic lookup of context variable (anywhere in the chain). | 3562 // Dynamic lookup of context variable (anywhere in the chain). |
3563 Node* name = jsgraph()->Constant(variable->name()); | 3563 Handle<Name> name = variable->name(); |
3564 Node* language = jsgraph()->Constant(language_mode()); | |
3565 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for | 3564 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for |
3566 // initializations of const declarations. | 3565 // initializations of const declarations. |
3567 const Operator* op = javascript()->CallRuntime(Runtime::kStoreLookupSlot); | 3566 Node* store = BuildDynamicStore(name, value); |
3568 Node* store = NewNode(op, value, current_context(), name, language); | |
3569 PrepareFrameState(store, bailout_id, combine); | 3567 PrepareFrameState(store, bailout_id, combine); |
3570 return store; | 3568 return store; |
3571 } | 3569 } |
3572 } | 3570 } |
3573 UNREACHABLE(); | 3571 UNREACHABLE(); |
3574 return nullptr; | 3572 return nullptr; |
3575 } | 3573 } |
3576 | 3574 |
3577 | 3575 |
3578 Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key, | 3576 Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key, |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3664 | 3662 |
3665 Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value, | 3663 Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value, |
3666 const VectorSlotPair& feedback) { | 3664 const VectorSlotPair& feedback) { |
3667 const Operator* op = | 3665 const Operator* op = |
3668 javascript()->StoreGlobal(language_mode(), name, feedback); | 3666 javascript()->StoreGlobal(language_mode(), name, feedback); |
3669 Node* node = NewNode(op, value, GetFunctionClosure()); | 3667 Node* node = NewNode(op, value, GetFunctionClosure()); |
3670 return node; | 3668 return node; |
3671 } | 3669 } |
3672 | 3670 |
3673 | 3671 |
3674 Node* AstGraphBuilder::BuildLoadImmutableObjectField(Node* object, int offset) { | 3672 Node* AstGraphBuilder::BuildDynamicLoad(Handle<Name> name, |
3675 return graph()->NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()), | 3673 TypeofMode typeof_mode) { |
3676 object, | 3674 Node* name_node = jsgraph()->Constant(name); |
3677 jsgraph()->IntPtrConstant(offset - kHeapObjectTag), | 3675 const Operator* op = |
3678 graph()->start(), graph()->start()); | 3676 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF |
| 3677 ? Runtime::kLoadLookupSlot |
| 3678 : Runtime::kLoadLookupSlotInsideTypeof); |
| 3679 Node* node = NewNode(op, name_node); |
| 3680 return node; |
3679 } | 3681 } |
3680 | 3682 |
3681 | 3683 |
| 3684 Node* AstGraphBuilder::BuildDynamicStore(Handle<Name> name, Node* value) { |
| 3685 Node* name_node = jsgraph()->Constant(name); |
| 3686 const Operator* op = javascript()->CallRuntime( |
| 3687 is_strict(language_mode()) ? Runtime::kStoreLookupSlot_Strict |
| 3688 : Runtime::kStoreLookupSlot_Sloppy); |
| 3689 Node* node = NewNode(op, name_node, value); |
| 3690 return node; |
| 3691 } |
| 3692 |
| 3693 |
3682 Node* AstGraphBuilder::BuildLoadGlobalObject() { | 3694 Node* AstGraphBuilder::BuildLoadGlobalObject() { |
3683 return BuildLoadNativeContextField(Context::EXTENSION_INDEX); | 3695 return BuildLoadNativeContextField(Context::EXTENSION_INDEX); |
3684 } | 3696 } |
3685 | 3697 |
3686 | 3698 |
3687 Node* AstGraphBuilder::BuildLoadNativeContextField(int index) { | 3699 Node* AstGraphBuilder::BuildLoadNativeContextField(int index) { |
3688 const Operator* op = | 3700 const Operator* op = |
3689 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true); | 3701 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true); |
3690 Node* native_context = NewNode(op, current_context()); | 3702 Node* native_context = NewNode(op, current_context()); |
3691 return NewNode(javascript()->LoadContext(0, index, true), native_context); | 3703 return NewNode(javascript()->LoadContext(0, index, true), native_context); |
3692 } | 3704 } |
3693 | 3705 |
3694 | 3706 |
3695 Node* AstGraphBuilder::BuildLoadFeedbackVector() { | |
3696 if (!feedback_vector_.is_set()) { | |
3697 Node* closure = GetFunctionClosure(); | |
3698 Node* shared = BuildLoadImmutableObjectField( | |
3699 closure, JSFunction::kSharedFunctionInfoOffset); | |
3700 Node* vector = BuildLoadImmutableObjectField( | |
3701 shared, SharedFunctionInfo::kFeedbackVectorOffset); | |
3702 feedback_vector_.set(vector); | |
3703 } | |
3704 return feedback_vector_.get(); | |
3705 } | |
3706 | |
3707 | |
3708 Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) { | 3707 Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) { |
3709 if (Node* node = TryFastToBoolean(input)) return node; | 3708 if (Node* node = TryFastToBoolean(input)) return node; |
3710 ToBooleanHints hints; | 3709 ToBooleanHints hints; |
3711 if (!type_hint_analysis_ || | 3710 if (!type_hint_analysis_ || |
3712 !type_hint_analysis_->GetToBooleanHints(feedback_id, &hints)) { | 3711 !type_hint_analysis_->GetToBooleanHints(feedback_id, &hints)) { |
3713 hints = ToBooleanHint::kAny; | 3712 hints = ToBooleanHint::kAny; |
3714 } | 3713 } |
3715 return NewNode(javascript()->ToBoolean(hints), input); | 3714 return NewNode(javascript()->ToBoolean(hints), input); |
3716 } | 3715 } |
3717 | 3716 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3916 // Perform global slot load. | 3915 // Perform global slot load. |
3917 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode); | 3916 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode); |
3918 states.AddToNode(fast, bailout_id, combine); | 3917 states.AddToNode(fast, bailout_id, combine); |
3919 environment()->Push(fast); | 3918 environment()->Push(fast); |
3920 } | 3919 } |
3921 slow_block.Break(); | 3920 slow_block.Break(); |
3922 environment()->Pop(); | 3921 environment()->Pop(); |
3923 fast_block.EndBlock(); | 3922 fast_block.EndBlock(); |
3924 | 3923 |
3925 // Slow case, because variable potentially shadowed. Perform dynamic lookup. | 3924 // Slow case, because variable potentially shadowed. Perform dynamic lookup. |
3926 const Operator* op = javascript()->LoadDynamic(name, typeof_mode); | 3925 Node* slow = BuildDynamicLoad(name, typeof_mode); |
3927 Node* slow = NewNode(op, BuildLoadFeedbackVector(), current_context()); | |
3928 states.AddToNode(slow, bailout_id, combine); | 3926 states.AddToNode(slow, bailout_id, combine); |
3929 environment()->Push(slow); | 3927 environment()->Push(slow); |
3930 slow_block.EndBlock(); | 3928 slow_block.EndBlock(); |
3931 | 3929 |
3932 return environment()->Pop(); | 3930 return environment()->Pop(); |
3933 } | 3931 } |
3934 | 3932 |
3935 if (mode == DYNAMIC_LOCAL) { | 3933 if (mode == DYNAMIC_LOCAL) { |
3936 uint32_t bitset = ComputeBitsetForDynamicContext(variable); | 3934 uint32_t bitset = ComputeBitsetForDynamicContext(variable); |
3937 if (bitset == kFullCheckRequired) return nullptr; | 3935 if (bitset == kFullCheckRequired) return nullptr; |
(...skipping 22 matching lines...) Expand all Loading... |
3960 Variable* local = variable->local_if_not_shadowed(); | 3958 Variable* local = variable->local_if_not_shadowed(); |
3961 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context. | 3959 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context. |
3962 Node* fast = BuildVariableLoad(local, bailout_id, states, feedback, combine, | 3960 Node* fast = BuildVariableLoad(local, bailout_id, states, feedback, combine, |
3963 typeof_mode); | 3961 typeof_mode); |
3964 environment()->Push(fast); | 3962 environment()->Push(fast); |
3965 slow_block.Break(); | 3963 slow_block.Break(); |
3966 environment()->Pop(); | 3964 environment()->Pop(); |
3967 fast_block.EndBlock(); | 3965 fast_block.EndBlock(); |
3968 | 3966 |
3969 // Slow case, because variable potentially shadowed. Perform dynamic lookup. | 3967 // Slow case, because variable potentially shadowed. Perform dynamic lookup. |
3970 const Operator* op = javascript()->LoadDynamic(name, typeof_mode); | 3968 Node* slow = BuildDynamicLoad(name, typeof_mode); |
3971 Node* slow = NewNode(op, BuildLoadFeedbackVector(), current_context()); | |
3972 states.AddToNode(slow, bailout_id, combine); | 3969 states.AddToNode(slow, bailout_id, combine); |
3973 environment()->Push(slow); | 3970 environment()->Push(slow); |
3974 slow_block.EndBlock(); | 3971 slow_block.EndBlock(); |
3975 | 3972 |
3976 return environment()->Pop(); | 3973 return environment()->Pop(); |
3977 } | 3974 } |
3978 | 3975 |
3979 return nullptr; | 3976 return nullptr; |
3980 } | 3977 } |
3981 | 3978 |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4355 // Phi does not exist yet, introduce one. | 4352 // Phi does not exist yet, introduce one. |
4356 value = NewPhi(inputs, value, control); | 4353 value = NewPhi(inputs, value, control); |
4357 value->ReplaceInput(inputs - 1, other); | 4354 value->ReplaceInput(inputs - 1, other); |
4358 } | 4355 } |
4359 return value; | 4356 return value; |
4360 } | 4357 } |
4361 | 4358 |
4362 } // namespace compiler | 4359 } // namespace compiler |
4363 } // namespace internal | 4360 } // namespace internal |
4364 } // namespace v8 | 4361 } // namespace v8 |
OLD | NEW |