Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/compiler/ast-graph-builder.cc

Issue 1424943008: [turbofan] Desugar lookup slot optimization in graph builder. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comment. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/compiler/control-builders.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 3044 matching lines...) Expand 10 before | Expand all | Expand 10 after
3055 return info()->language_mode(); 3055 return info()->language_mode();
3056 } 3056 }
3057 3057
3058 3058
3059 VectorSlotPair AstGraphBuilder::CreateVectorSlotPair( 3059 VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
3060 FeedbackVectorSlot slot) const { 3060 FeedbackVectorSlot slot) const {
3061 return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot); 3061 return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot);
3062 } 3062 }
3063 3063
3064 3064
3065 namespace {
3066
3067 // Limit of context chain length to which inline check is possible.
3068 const int kMaxCheckDepth = 30;
3069
3070 // Sentinel for {TryLoadDynamicVariable} disabling inline checks.
3071 const uint32_t kFullCheckRequired = -1;
3072
3073 } // namespace
3074
3075
3065 uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) { 3076 uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) {
3066 DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode()); 3077 DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
3067 bool found_eval_scope = false; 3078 bool found_eval_scope = false;
3068 uint32_t check_depths = 0; 3079 uint32_t check_depths = 0;
3069 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) { 3080 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3070 if (s->num_heap_slots() <= 0) continue; 3081 if (s->num_heap_slots() <= 0) continue;
3071 // TODO(mstarzinger): If we have reached an eval scope, we check all 3082 // TODO(mstarzinger): If we have reached an eval scope, we check all
3072 // extensions from this point. Replicated from full-codegen, figure out 3083 // extensions from this point. Replicated from full-codegen, figure out
3073 // whether this is still needed. If not, drop {found_eval_scope} below. 3084 // whether this is still needed. If not, drop {found_eval_scope} below.
3074 if (s->is_eval_scope()) found_eval_scope = true; 3085 if (s->is_eval_scope()) found_eval_scope = true;
3075 if (!s->calls_sloppy_eval() && !found_eval_scope) continue; 3086 if (!s->calls_sloppy_eval() && !found_eval_scope) continue;
3076 int depth = current_scope()->ContextChainLength(s); 3087 int depth = current_scope()->ContextChainLength(s);
3077 if (depth > DynamicGlobalAccess::kMaxCheckDepth) { 3088 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3078 return DynamicGlobalAccess::kFullCheckRequired;
3079 }
3080 check_depths |= 1 << depth; 3089 check_depths |= 1 << depth;
3081 } 3090 }
3082 return check_depths; 3091 return check_depths;
3083 } 3092 }
3084 3093
3085 3094
3086 uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) { 3095 uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
3087 DCHECK_EQ(DYNAMIC_LOCAL, variable->mode()); 3096 DCHECK_EQ(DYNAMIC_LOCAL, variable->mode());
3088 uint32_t check_depths = 0; 3097 uint32_t check_depths = 0;
3089 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) { 3098 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3090 if (s->num_heap_slots() <= 0) continue; 3099 if (s->num_heap_slots() <= 0) continue;
3091 if (!s->calls_sloppy_eval() && s != variable->scope()) continue; 3100 if (!s->calls_sloppy_eval() && s != variable->scope()) continue;
3092 int depth = current_scope()->ContextChainLength(s); 3101 int depth = current_scope()->ContextChainLength(s);
3093 if (depth > DynamicContextAccess::kMaxCheckDepth) { 3102 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3094 return DynamicContextAccess::kFullCheckRequired;
3095 }
3096 check_depths |= 1 << depth; 3103 check_depths |= 1 << depth;
3097 if (s == variable->scope()) break; 3104 if (s == variable->scope()) break;
3098 } 3105 }
3099 return check_depths; 3106 return check_depths;
3100 } 3107 }
3101 3108
3102 3109
3103 Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) { 3110 Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
3104 DCHECK(environment()->stack_height() >= arity); 3111 DCHECK(environment()->stack_height() >= arity);
3105 Node** all = info()->zone()->NewArray<Node*>(arity); 3112 Node** all = info()->zone()->NewArray<Node*>(arity);
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
3373 Node* undefined = jsgraph()->UndefinedConstant(); 3380 Node* undefined = jsgraph()->UndefinedConstant();
3374 value = BuildHoleCheckSilent(value, undefined, value); 3381 value = BuildHoleCheckSilent(value, undefined, value);
3375 } else if (mode == LET || mode == CONST) { 3382 } else if (mode == LET || mode == CONST) {
3376 // Perform check for uninitialized let/const variables. 3383 // Perform check for uninitialized let/const variables.
3377 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id); 3384 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
3378 } 3385 }
3379 return value; 3386 return value;
3380 } 3387 }
3381 case VariableLocation::LOOKUP: { 3388 case VariableLocation::LOOKUP: {
3382 // Dynamic lookup of context variable (anywhere in the chain). 3389 // Dynamic lookup of context variable (anywhere in the chain).
3383 Node* value = jsgraph()->TheHoleConstant();
3384 Handle<String> name = variable->name(); 3390 Handle<String> name = variable->name();
3385 if (mode == DYNAMIC_GLOBAL) { 3391 if (Node* node =
3386 uint32_t check_bitset = ComputeBitsetForDynamicGlobal(variable); 3392 TryLoadDynamicVariable(variable, name, bailout_id, states,
3387 const Operator* op = javascript()->LoadDynamicGlobal( 3393 feedback, combine, typeof_mode)) {
3388 name, check_bitset, feedback, typeof_mode); 3394 return node;
3389 value = NewNode(op, BuildLoadFeedbackVector(), current_context());
3390 states.AddToNode(value, bailout_id, combine);
3391 } else if (mode == DYNAMIC_LOCAL) {
3392 Variable* local = variable->local_if_not_shadowed();
3393 DCHECK(local->location() ==
3394 VariableLocation::CONTEXT); // Must be context.
3395 int depth = current_scope()->ContextChainLength(local->scope());
3396 uint32_t check_bitset = ComputeBitsetForDynamicContext(variable);
3397 const Operator* op = javascript()->LoadDynamicContext(
3398 name, check_bitset, depth, local->index());
3399 value = NewNode(op, current_context());
3400 PrepareFrameState(value, bailout_id, combine);
3401 VariableMode local_mode = local->mode();
3402 if (local_mode == CONST_LEGACY) {
3403 // Perform check for uninitialized legacy const variables.
3404 Node* undefined = jsgraph()->UndefinedConstant();
3405 value = BuildHoleCheckSilent(value, undefined, value);
3406 } else if (local_mode == LET || local_mode == CONST) {
3407 // Perform check for uninitialized let/const variables.
3408 value = BuildHoleCheckThenThrow(value, local, value, bailout_id);
3409 }
3410 } else if (mode == DYNAMIC) {
3411 uint32_t check_bitset = DynamicGlobalAccess::kFullCheckRequired;
3412 const Operator* op = javascript()->LoadDynamicGlobal(
3413 name, check_bitset, feedback, typeof_mode);
3414 value = NewNode(op, BuildLoadFeedbackVector(), current_context());
3415 states.AddToNode(value, bailout_id, combine);
3416 } 3395 }
3396 const Operator* op = javascript()->LoadDynamic(name, typeof_mode);
3397 Node* value = NewNode(op, BuildLoadFeedbackVector(), current_context());
3398 states.AddToNode(value, bailout_id, combine);
3417 return value; 3399 return value;
3418 } 3400 }
3419 } 3401 }
3420 UNREACHABLE(); 3402 UNREACHABLE();
3421 return NULL; 3403 return NULL;
3422 } 3404 }
3423 3405
3424 3406
3425 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, 3407 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
3426 BailoutId bailout_id, 3408 BailoutId bailout_id,
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
3900 3882
3901 3883
3902 Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) { 3884 Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) {
3903 // Optimize global constants like "undefined", "Infinity", and "NaN". 3885 // Optimize global constants like "undefined", "Infinity", and "NaN".
3904 Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name); 3886 Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name);
3905 if (!constant_value.is_null()) return jsgraph()->Constant(constant_value); 3887 if (!constant_value.is_null()) return jsgraph()->Constant(constant_value);
3906 return nullptr; 3888 return nullptr;
3907 } 3889 }
3908 3890
3909 3891
3892 Node* AstGraphBuilder::TryLoadDynamicVariable(
3893 Variable* variable, Handle<String> name, BailoutId bailout_id,
3894 FrameStateBeforeAndAfter& states, const VectorSlotPair& feedback,
3895 OutputFrameStateCombine combine, TypeofMode typeof_mode) {
3896 VariableMode mode = variable->mode();
3897
3898 if (mode == DYNAMIC_GLOBAL) {
3899 uint32_t bitset = ComputeBitsetForDynamicGlobal(variable);
3900 if (bitset == kFullCheckRequired) return nullptr;
3901
3902 // We are using two blocks to model fast and slow cases.
3903 BlockBuilder fast_block(this);
3904 BlockBuilder slow_block(this);
3905 environment()->Push(jsgraph()->TheHoleConstant());
3906 slow_block.BeginBlock();
3907 environment()->Pop();
3908 fast_block.BeginBlock();
3909
3910 // Perform checks whether the fast mode applies, by looking for any
3911 // extension object which might shadow the optimistic declaration.
3912 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3913 if ((bitset & 1) == 0) continue;
3914 Node* load = NewNode(
3915 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3916 current_context());
3917 Node* check =
3918 NewNode(javascript()->CallRuntime(Runtime::kInlineIsSmi, 1), load);
3919 fast_block.BreakUnless(check, BranchHint::kTrue);
3920 }
3921
3922 // Fast case, because variable is not shadowed. Perform global slot load.
3923 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
3924 states.AddToNode(fast, bailout_id, combine);
3925 environment()->Push(fast);
3926 slow_block.Break();
3927 environment()->Pop();
3928 fast_block.EndBlock();
3929
3930 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
3931 const Operator* op = javascript()->LoadDynamic(name, typeof_mode);
3932 Node* slow = NewNode(op, BuildLoadFeedbackVector(), current_context());
3933 states.AddToNode(slow, bailout_id, combine);
3934 environment()->Push(slow);
3935 slow_block.EndBlock();
3936
3937 return environment()->Pop();
3938 }
3939
3940 if (mode == DYNAMIC_LOCAL) {
3941 uint32_t bitset = ComputeBitsetForDynamicContext(variable);
3942 if (bitset == kFullCheckRequired) return nullptr;
3943
3944 // We are using two blocks to model fast and slow cases.
3945 BlockBuilder fast_block(this);
3946 BlockBuilder slow_block(this);
3947 environment()->Push(jsgraph()->TheHoleConstant());
3948 slow_block.BeginBlock();
3949 environment()->Pop();
3950 fast_block.BeginBlock();
3951
3952 // Perform checks whether the fast mode applies, by looking for any
3953 // extension object which might shadow the optimistic declaration.
3954 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3955 if ((bitset & 1) == 0) continue;
3956 Node* load = NewNode(
3957 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3958 current_context());
3959 Node* check =
3960 NewNode(javascript()->CallRuntime(Runtime::kInlineIsSmi, 1), load);
3961 fast_block.BreakUnless(check, BranchHint::kTrue);
3962 }
3963
3964 // Fast case, because variable is not shadowed. Perform context slot load.
3965 Variable* local = variable->local_if_not_shadowed();
3966 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context.
3967 Node* fast = BuildVariableLoad(local, bailout_id, states, feedback, combine,
3968 typeof_mode);
3969 environment()->Push(fast);
3970 slow_block.Break();
3971 environment()->Pop();
3972 fast_block.EndBlock();
3973
3974 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
3975 const Operator* op = javascript()->LoadDynamic(name, typeof_mode);
3976 Node* slow = NewNode(op, BuildLoadFeedbackVector(), current_context());
3977 states.AddToNode(slow, bailout_id, combine);
3978 environment()->Push(slow);
3979 slow_block.EndBlock();
3980
3981 return environment()->Pop();
3982 }
3983
3984 return nullptr;
3985 }
3986
3987
3910 Node* AstGraphBuilder::TryFastToBoolean(Node* input) { 3988 Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
3911 switch (input->opcode()) { 3989 switch (input->opcode()) {
3912 case IrOpcode::kNumberConstant: { 3990 case IrOpcode::kNumberConstant: {
3913 NumberMatcher m(input); 3991 NumberMatcher m(input);
3914 return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN()); 3992 return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
3915 } 3993 }
3916 case IrOpcode::kHeapConstant: { 3994 case IrOpcode::kHeapConstant: {
3917 Handle<HeapObject> object = HeapObjectMatcher(input).Value(); 3995 Handle<HeapObject> object = HeapObjectMatcher(input).Value();
3918 return jsgraph_->BooleanConstant(object->BooleanValue()); 3996 return jsgraph_->BooleanConstant(object->BooleanValue());
3919 } 3997 }
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
4282 // Phi does not exist yet, introduce one. 4360 // Phi does not exist yet, introduce one.
4283 value = NewPhi(inputs, value, control); 4361 value = NewPhi(inputs, value, control);
4284 value->ReplaceInput(inputs - 1, other); 4362 value->ReplaceInput(inputs - 1, other);
4285 } 4363 }
4286 return value; 4364 return value;
4287 } 4365 }
4288 4366
4289 } // namespace compiler 4367 } // namespace compiler
4290 } // namespace internal 4368 } // namespace internal
4291 } // namespace v8 4369 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/compiler/control-builders.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698