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/js-type-feedback.h" | 10 #include "src/compiler/js-type-feedback.h" |
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 if (FLAG_trace_environment_liveness) { | 631 if (FLAG_trace_environment_liveness) { |
632 OFStream os(stdout); | 632 OFStream os(stdout); |
633 liveness_analyzer()->Print(os); | 633 liveness_analyzer()->Print(os); |
634 } | 634 } |
635 } | 635 } |
636 | 636 |
637 | 637 |
638 // Gets the bailout id just before reading a variable proxy, but only for | 638 // Gets the bailout id just before reading a variable proxy, but only for |
639 // unallocated variables. | 639 // unallocated variables. |
640 static BailoutId BeforeId(VariableProxy* proxy) { | 640 static BailoutId BeforeId(VariableProxy* proxy) { |
641 return proxy->var()->location() == Variable::UNALLOCATED ? proxy->BeforeId() | 641 return proxy->var()->IsUnallocatedOrGlobalSlot() ? proxy->BeforeId() |
642 : BailoutId::None(); | 642 : BailoutId::None(); |
643 } | 643 } |
644 | 644 |
645 | 645 |
646 static const char* GetDebugParameterName(Zone* zone, Scope* scope, int index) { | 646 static const char* GetDebugParameterName(Zone* zone, Scope* scope, int index) { |
647 #if DEBUG | 647 #if DEBUG |
648 const AstRawString* name = scope->parameter(index)->raw_name(); | 648 const AstRawString* name = scope->parameter(index)->raw_name(); |
649 if (name && name->length() > 0) { | 649 if (name && name->length() > 0) { |
650 char* data = zone->NewArray<char>(name->length() + 1); | 650 char* data = zone->NewArray<char>(name->length() + 1); |
651 data[name->length()] = 0; | 651 data[name->length()] = 0; |
652 memcpy(data, name->raw_data(), name->length()); | 652 memcpy(data, name->raw_data(), name->length()); |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); | 1050 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); |
1051 } | 1051 } |
1052 } | 1052 } |
1053 | 1053 |
1054 | 1054 |
1055 void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) { | 1055 void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) { |
1056 Variable* variable = decl->proxy()->var(); | 1056 Variable* variable = decl->proxy()->var(); |
1057 VariableMode mode = decl->mode(); | 1057 VariableMode mode = decl->mode(); |
1058 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; | 1058 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; |
1059 switch (variable->location()) { | 1059 switch (variable->location()) { |
1060 case Variable::UNALLOCATED: { | 1060 case VariableLocation::GLOBAL: |
| 1061 case VariableLocation::UNALLOCATED: { |
1061 Handle<Oddball> value = variable->binding_needs_init() | 1062 Handle<Oddball> value = variable->binding_needs_init() |
1062 ? isolate()->factory()->the_hole_value() | 1063 ? isolate()->factory()->the_hole_value() |
1063 : isolate()->factory()->undefined_value(); | 1064 : isolate()->factory()->undefined_value(); |
1064 globals()->push_back(variable->name()); | 1065 globals()->push_back(variable->name()); |
1065 globals()->push_back(value); | 1066 globals()->push_back(value); |
1066 break; | 1067 break; |
1067 } | 1068 } |
1068 case Variable::PARAMETER: | 1069 case VariableLocation::PARAMETER: |
1069 case Variable::LOCAL: | 1070 case VariableLocation::LOCAL: |
1070 if (hole_init) { | 1071 if (hole_init) { |
1071 Node* value = jsgraph()->TheHoleConstant(); | 1072 Node* value = jsgraph()->TheHoleConstant(); |
1072 environment()->Bind(variable, value); | 1073 environment()->Bind(variable, value); |
1073 } | 1074 } |
1074 break; | 1075 break; |
1075 case Variable::CONTEXT: | 1076 case VariableLocation::CONTEXT: |
1076 if (hole_init) { | 1077 if (hole_init) { |
1077 Node* value = jsgraph()->TheHoleConstant(); | 1078 Node* value = jsgraph()->TheHoleConstant(); |
1078 const Operator* op = javascript()->StoreContext(0, variable->index()); | 1079 const Operator* op = javascript()->StoreContext(0, variable->index()); |
1079 NewNode(op, current_context(), value); | 1080 NewNode(op, current_context(), value); |
1080 } | 1081 } |
1081 break; | 1082 break; |
1082 case Variable::LOOKUP: | 1083 case VariableLocation::LOOKUP: |
1083 UNIMPLEMENTED(); | 1084 UNIMPLEMENTED(); |
1084 } | 1085 } |
1085 } | 1086 } |
1086 | 1087 |
1087 | 1088 |
1088 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 1089 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
1089 Variable* variable = decl->proxy()->var(); | 1090 Variable* variable = decl->proxy()->var(); |
1090 switch (variable->location()) { | 1091 switch (variable->location()) { |
1091 case Variable::UNALLOCATED: { | 1092 case VariableLocation::GLOBAL: |
| 1093 case VariableLocation::UNALLOCATED: { |
1092 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo( | 1094 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo( |
1093 decl->fun(), info()->script(), info()); | 1095 decl->fun(), info()->script(), info()); |
1094 // Check for stack-overflow exception. | 1096 // Check for stack-overflow exception. |
1095 if (function.is_null()) return SetStackOverflow(); | 1097 if (function.is_null()) return SetStackOverflow(); |
1096 globals()->push_back(variable->name()); | 1098 globals()->push_back(variable->name()); |
1097 globals()->push_back(function); | 1099 globals()->push_back(function); |
1098 break; | 1100 break; |
1099 } | 1101 } |
1100 case Variable::PARAMETER: | 1102 case VariableLocation::PARAMETER: |
1101 case Variable::LOCAL: { | 1103 case VariableLocation::LOCAL: { |
1102 VisitForValue(decl->fun()); | 1104 VisitForValue(decl->fun()); |
1103 Node* value = environment()->Pop(); | 1105 Node* value = environment()->Pop(); |
1104 environment()->Bind(variable, value); | 1106 environment()->Bind(variable, value); |
1105 break; | 1107 break; |
1106 } | 1108 } |
1107 case Variable::CONTEXT: { | 1109 case VariableLocation::CONTEXT: { |
1108 VisitForValue(decl->fun()); | 1110 VisitForValue(decl->fun()); |
1109 Node* value = environment()->Pop(); | 1111 Node* value = environment()->Pop(); |
1110 const Operator* op = javascript()->StoreContext(0, variable->index()); | 1112 const Operator* op = javascript()->StoreContext(0, variable->index()); |
1111 NewNode(op, current_context(), value); | 1113 NewNode(op, current_context(), value); |
1112 break; | 1114 break; |
1113 } | 1115 } |
1114 case Variable::LOOKUP: | 1116 case VariableLocation::LOOKUP: |
1115 UNIMPLEMENTED(); | 1117 UNIMPLEMENTED(); |
1116 } | 1118 } |
1117 } | 1119 } |
1118 | 1120 |
1119 | 1121 |
1120 void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) { | 1122 void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) { |
1121 UNREACHABLE(); | 1123 UNREACHABLE(); |
1122 } | 1124 } |
1123 | 1125 |
1124 | 1126 |
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2077 | 2079 |
2078 // Left-hand side can only be a property, a global or a variable slot. | 2080 // Left-hand side can only be a property, a global or a variable slot. |
2079 Property* property = expr->target()->AsProperty(); | 2081 Property* property = expr->target()->AsProperty(); |
2080 LhsKind assign_type = Property::GetAssignType(property); | 2082 LhsKind assign_type = Property::GetAssignType(property); |
2081 bool needs_frame_state_before = true; | 2083 bool needs_frame_state_before = true; |
2082 | 2084 |
2083 // Evaluate LHS expression. | 2085 // Evaluate LHS expression. |
2084 switch (assign_type) { | 2086 switch (assign_type) { |
2085 case VARIABLE: { | 2087 case VARIABLE: { |
2086 Variable* variable = expr->target()->AsVariableProxy()->var(); | 2088 Variable* variable = expr->target()->AsVariableProxy()->var(); |
2087 if (variable->location() == Variable::PARAMETER || | 2089 if (variable->location() == VariableLocation::PARAMETER || |
2088 variable->location() == Variable::LOCAL || | 2090 variable->location() == VariableLocation::LOCAL || |
2089 variable->location() == Variable::CONTEXT) { | 2091 variable->location() == VariableLocation::CONTEXT) { |
2090 needs_frame_state_before = false; | 2092 needs_frame_state_before = false; |
2091 } | 2093 } |
2092 break; | 2094 break; |
2093 } | 2095 } |
2094 case NAMED_PROPERTY: | 2096 case NAMED_PROPERTY: |
2095 VisitForValue(property->obj()); | 2097 VisitForValue(property->obj()); |
2096 break; | 2098 break; |
2097 case KEYED_PROPERTY: | 2099 case KEYED_PROPERTY: |
2098 VisitForValue(property->obj()); | 2100 VisitForValue(property->obj()); |
2099 VisitForValue(property->key()); | 2101 VisitForValue(property->key()); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2335 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); | 2337 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
2336 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); | 2338 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); |
2337 callee_value = | 2339 callee_value = |
2338 BuildVariableLoad(proxy->var(), expr->expression()->id(), states, | 2340 BuildVariableLoad(proxy->var(), expr->expression()->id(), states, |
2339 pair, OutputFrameStateCombine::Push()); | 2341 pair, OutputFrameStateCombine::Push()); |
2340 receiver_value = jsgraph()->UndefinedConstant(); | 2342 receiver_value = jsgraph()->UndefinedConstant(); |
2341 break; | 2343 break; |
2342 } | 2344 } |
2343 case Call::LOOKUP_SLOT_CALL: { | 2345 case Call::LOOKUP_SLOT_CALL: { |
2344 Variable* variable = callee->AsVariableProxy()->var(); | 2346 Variable* variable = callee->AsVariableProxy()->var(); |
2345 DCHECK(variable->location() == Variable::LOOKUP); | 2347 DCHECK(variable->location() == VariableLocation::LOOKUP); |
2346 Node* name = jsgraph()->Constant(variable->name()); | 2348 Node* name = jsgraph()->Constant(variable->name()); |
2347 const Operator* op = | 2349 const Operator* op = |
2348 javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2); | 2350 javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2); |
2349 Node* pair = NewNode(op, current_context(), name); | 2351 Node* pair = NewNode(op, current_context(), name); |
2350 callee_value = NewNode(common()->Projection(0), pair); | 2352 callee_value = NewNode(common()->Projection(0), pair); |
2351 receiver_value = NewNode(common()->Projection(1), pair); | 2353 receiver_value = NewNode(common()->Projection(1), pair); |
2352 | 2354 |
2353 PrepareFrameState(pair, expr->LookupId(), | 2355 PrepareFrameState(pair, expr->LookupId(), |
2354 OutputFrameStateCombine::Push(2)); | 2356 OutputFrameStateCombine::Push(2)); |
2355 break; | 2357 break; |
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3229 | 3231 |
3230 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, | 3232 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, |
3231 BailoutId bailout_id, | 3233 BailoutId bailout_id, |
3232 FrameStateBeforeAndAfter& states, | 3234 FrameStateBeforeAndAfter& states, |
3233 const VectorSlotPair& feedback, | 3235 const VectorSlotPair& feedback, |
3234 OutputFrameStateCombine combine, | 3236 OutputFrameStateCombine combine, |
3235 ContextualMode contextual_mode) { | 3237 ContextualMode contextual_mode) { |
3236 Node* the_hole = jsgraph()->TheHoleConstant(); | 3238 Node* the_hole = jsgraph()->TheHoleConstant(); |
3237 VariableMode mode = variable->mode(); | 3239 VariableMode mode = variable->mode(); |
3238 switch (variable->location()) { | 3240 switch (variable->location()) { |
3239 case Variable::UNALLOCATED: { | 3241 case VariableLocation::GLOBAL: |
| 3242 case VariableLocation::UNALLOCATED: { |
3240 // Global var, const, or let variable. | 3243 // Global var, const, or let variable. |
3241 Node* global = BuildLoadGlobalObject(); | 3244 Node* global = BuildLoadGlobalObject(); |
3242 Handle<Name> name = variable->name(); | 3245 Handle<Name> name = variable->name(); |
3243 Node* value = BuildGlobalLoad(global, name, feedback, contextual_mode); | 3246 Node* value = BuildGlobalLoad(global, name, feedback, contextual_mode); |
3244 states.AddToNode(value, bailout_id, combine); | 3247 states.AddToNode(value, bailout_id, combine); |
3245 return value; | 3248 return value; |
3246 } | 3249 } |
3247 case Variable::PARAMETER: | 3250 case VariableLocation::PARAMETER: |
3248 case Variable::LOCAL: { | 3251 case VariableLocation::LOCAL: { |
3249 // Local var, const, or let variable. | 3252 // Local var, const, or let variable. |
3250 Node* value = environment()->Lookup(variable); | 3253 Node* value = environment()->Lookup(variable); |
3251 if (mode == CONST_LEGACY) { | 3254 if (mode == CONST_LEGACY) { |
3252 // Perform check for uninitialized legacy const variables. | 3255 // Perform check for uninitialized legacy const variables. |
3253 if (value->op() == the_hole->op()) { | 3256 if (value->op() == the_hole->op()) { |
3254 value = jsgraph()->UndefinedConstant(); | 3257 value = jsgraph()->UndefinedConstant(); |
3255 } else if (value->opcode() == IrOpcode::kPhi) { | 3258 } else if (value->opcode() == IrOpcode::kPhi) { |
3256 Node* undefined = jsgraph()->UndefinedConstant(); | 3259 Node* undefined = jsgraph()->UndefinedConstant(); |
3257 value = BuildHoleCheckSilent(value, undefined, value); | 3260 value = BuildHoleCheckSilent(value, undefined, value); |
3258 } | 3261 } |
3259 } else if (mode == LET || mode == CONST) { | 3262 } else if (mode == LET || mode == CONST) { |
3260 // Perform check for uninitialized let/const variables. | 3263 // Perform check for uninitialized let/const variables. |
3261 if (value->op() == the_hole->op()) { | 3264 if (value->op() == the_hole->op()) { |
3262 value = BuildThrowReferenceError(variable, bailout_id); | 3265 value = BuildThrowReferenceError(variable, bailout_id); |
3263 } else if (value->opcode() == IrOpcode::kPhi) { | 3266 } else if (value->opcode() == IrOpcode::kPhi) { |
3264 value = BuildHoleCheckThrow(value, variable, value, bailout_id); | 3267 value = BuildHoleCheckThrow(value, variable, value, bailout_id); |
3265 } | 3268 } |
3266 } | 3269 } |
3267 return value; | 3270 return value; |
3268 } | 3271 } |
3269 case Variable::CONTEXT: { | 3272 case VariableLocation::CONTEXT: { |
3270 // Context variable (potentially up the context chain). | 3273 // Context variable (potentially up the context chain). |
3271 int depth = current_scope()->ContextChainLength(variable->scope()); | 3274 int depth = current_scope()->ContextChainLength(variable->scope()); |
3272 bool immutable = variable->maybe_assigned() == kNotAssigned; | 3275 bool immutable = variable->maybe_assigned() == kNotAssigned; |
3273 const Operator* op = | 3276 const Operator* op = |
3274 javascript()->LoadContext(depth, variable->index(), immutable); | 3277 javascript()->LoadContext(depth, variable->index(), immutable); |
3275 Node* value = NewNode(op, current_context()); | 3278 Node* value = NewNode(op, current_context()); |
3276 // TODO(titzer): initialization checks are redundant for already | 3279 // TODO(titzer): initialization checks are redundant for already |
3277 // initialized immutable context loads, but only specialization knows. | 3280 // initialized immutable context loads, but only specialization knows. |
3278 // Maybe specializer should be a parameter to the graph builder? | 3281 // Maybe specializer should be a parameter to the graph builder? |
3279 if (mode == CONST_LEGACY) { | 3282 if (mode == CONST_LEGACY) { |
3280 // Perform check for uninitialized legacy const variables. | 3283 // Perform check for uninitialized legacy const variables. |
3281 Node* undefined = jsgraph()->UndefinedConstant(); | 3284 Node* undefined = jsgraph()->UndefinedConstant(); |
3282 value = BuildHoleCheckSilent(value, undefined, value); | 3285 value = BuildHoleCheckSilent(value, undefined, value); |
3283 } else if (mode == LET || mode == CONST) { | 3286 } else if (mode == LET || mode == CONST) { |
3284 // Perform check for uninitialized let/const variables. | 3287 // Perform check for uninitialized let/const variables. |
3285 value = BuildHoleCheckThrow(value, variable, value, bailout_id); | 3288 value = BuildHoleCheckThrow(value, variable, value, bailout_id); |
3286 } | 3289 } |
3287 return value; | 3290 return value; |
3288 } | 3291 } |
3289 case Variable::LOOKUP: { | 3292 case VariableLocation::LOOKUP: { |
3290 // Dynamic lookup of context variable (anywhere in the chain). | 3293 // Dynamic lookup of context variable (anywhere in the chain). |
3291 Node* value = jsgraph()->TheHoleConstant(); | 3294 Node* value = jsgraph()->TheHoleConstant(); |
3292 Handle<String> name = variable->name(); | 3295 Handle<String> name = variable->name(); |
3293 if (mode == DYNAMIC_GLOBAL) { | 3296 if (mode == DYNAMIC_GLOBAL) { |
3294 uint32_t check_bitset = ComputeBitsetForDynamicGlobal(variable); | 3297 uint32_t check_bitset = ComputeBitsetForDynamicGlobal(variable); |
3295 const Operator* op = javascript()->LoadDynamicGlobal( | 3298 const Operator* op = javascript()->LoadDynamicGlobal( |
3296 name, check_bitset, feedback, contextual_mode); | 3299 name, check_bitset, feedback, contextual_mode); |
3297 value = NewNode(op, BuildLoadFeedbackVector(), current_context()); | 3300 value = NewNode(op, BuildLoadFeedbackVector(), current_context()); |
3298 states.AddToNode(value, bailout_id, combine); | 3301 states.AddToNode(value, bailout_id, combine); |
3299 } else if (mode == DYNAMIC_LOCAL) { | 3302 } else if (mode == DYNAMIC_LOCAL) { |
3300 Variable* local = variable->local_if_not_shadowed(); | 3303 Variable* local = variable->local_if_not_shadowed(); |
3301 DCHECK(local->location() == Variable::CONTEXT); // Must be context. | 3304 DCHECK(local->location() == |
| 3305 VariableLocation::CONTEXT); // Must be context. |
3302 int depth = current_scope()->ContextChainLength(local->scope()); | 3306 int depth = current_scope()->ContextChainLength(local->scope()); |
3303 uint32_t check_bitset = ComputeBitsetForDynamicContext(variable); | 3307 uint32_t check_bitset = ComputeBitsetForDynamicContext(variable); |
3304 const Operator* op = javascript()->LoadDynamicContext( | 3308 const Operator* op = javascript()->LoadDynamicContext( |
3305 name, check_bitset, depth, local->index()); | 3309 name, check_bitset, depth, local->index()); |
3306 value = NewNode(op, current_context()); | 3310 value = NewNode(op, current_context()); |
3307 PrepareFrameState(value, bailout_id, combine); | 3311 PrepareFrameState(value, bailout_id, combine); |
3308 VariableMode local_mode = local->mode(); | 3312 VariableMode local_mode = local->mode(); |
3309 if (local_mode == CONST_LEGACY) { | 3313 if (local_mode == CONST_LEGACY) { |
3310 // Perform check for uninitialized legacy const variables. | 3314 // Perform check for uninitialized legacy const variables. |
3311 Node* undefined = jsgraph()->UndefinedConstant(); | 3315 Node* undefined = jsgraph()->UndefinedConstant(); |
(...skipping 14 matching lines...) Expand all Loading... |
3326 } | 3330 } |
3327 UNREACHABLE(); | 3331 UNREACHABLE(); |
3328 return NULL; | 3332 return NULL; |
3329 } | 3333 } |
3330 | 3334 |
3331 | 3335 |
3332 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, | 3336 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, |
3333 BailoutId bailout_id, | 3337 BailoutId bailout_id, |
3334 OutputFrameStateCombine combine) { | 3338 OutputFrameStateCombine combine) { |
3335 switch (variable->location()) { | 3339 switch (variable->location()) { |
3336 case Variable::UNALLOCATED: { | 3340 case VariableLocation::GLOBAL: |
| 3341 case VariableLocation::UNALLOCATED: { |
3337 // Global var, const, or let variable. | 3342 // Global var, const, or let variable. |
3338 Node* global = BuildLoadGlobalObject(); | 3343 Node* global = BuildLoadGlobalObject(); |
3339 Node* name = jsgraph()->Constant(variable->name()); | 3344 Node* name = jsgraph()->Constant(variable->name()); |
3340 const Operator* op = javascript()->DeleteProperty(language_mode()); | 3345 const Operator* op = javascript()->DeleteProperty(language_mode()); |
3341 Node* result = NewNode(op, global, name); | 3346 Node* result = NewNode(op, global, name); |
3342 PrepareFrameState(result, bailout_id, combine); | 3347 PrepareFrameState(result, bailout_id, combine); |
3343 return result; | 3348 return result; |
3344 } | 3349 } |
3345 case Variable::PARAMETER: | 3350 case VariableLocation::PARAMETER: |
3346 case Variable::LOCAL: | 3351 case VariableLocation::LOCAL: |
3347 case Variable::CONTEXT: { | 3352 case VariableLocation::CONTEXT: { |
3348 // Local var, const, or let variable or context variable. | 3353 // Local var, const, or let variable or context variable. |
3349 return jsgraph()->BooleanConstant(variable->HasThisName(isolate())); | 3354 return jsgraph()->BooleanConstant(variable->HasThisName(isolate())); |
3350 } | 3355 } |
3351 case Variable::LOOKUP: { | 3356 case VariableLocation::LOOKUP: { |
3352 // Dynamic lookup of context variable (anywhere in the chain). | 3357 // Dynamic lookup of context variable (anywhere in the chain). |
3353 Node* name = jsgraph()->Constant(variable->name()); | 3358 Node* name = jsgraph()->Constant(variable->name()); |
3354 const Operator* op = | 3359 const Operator* op = |
3355 javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2); | 3360 javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2); |
3356 Node* result = NewNode(op, current_context(), name); | 3361 Node* result = NewNode(op, current_context(), name); |
3357 PrepareFrameState(result, bailout_id, combine); | 3362 PrepareFrameState(result, bailout_id, combine); |
3358 return result; | 3363 return result; |
3359 } | 3364 } |
3360 } | 3365 } |
3361 UNREACHABLE(); | 3366 UNREACHABLE(); |
3362 return NULL; | 3367 return NULL; |
3363 } | 3368 } |
3364 | 3369 |
3365 | 3370 |
3366 Node* AstGraphBuilder::BuildVariableAssignment( | 3371 Node* AstGraphBuilder::BuildVariableAssignment( |
3367 Variable* variable, Node* value, Token::Value op, | 3372 Variable* variable, Node* value, Token::Value op, |
3368 const VectorSlotPair& feedback, BailoutId bailout_id, | 3373 const VectorSlotPair& feedback, BailoutId bailout_id, |
3369 FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) { | 3374 FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) { |
3370 Node* the_hole = jsgraph()->TheHoleConstant(); | 3375 Node* the_hole = jsgraph()->TheHoleConstant(); |
3371 VariableMode mode = variable->mode(); | 3376 VariableMode mode = variable->mode(); |
3372 switch (variable->location()) { | 3377 switch (variable->location()) { |
3373 case Variable::UNALLOCATED: { | 3378 case VariableLocation::GLOBAL: |
| 3379 case VariableLocation::UNALLOCATED: { |
3374 // Global var, const, or let variable. | 3380 // Global var, const, or let variable. |
3375 Node* global = BuildLoadGlobalObject(); | 3381 Node* global = BuildLoadGlobalObject(); |
3376 Handle<Name> name = variable->name(); | 3382 Handle<Name> name = variable->name(); |
3377 Node* store = BuildGlobalStore(global, name, value, feedback, | 3383 Node* store = BuildGlobalStore(global, name, value, feedback, |
3378 TypeFeedbackId::None()); | 3384 TypeFeedbackId::None()); |
3379 states.AddToNode(store, bailout_id, combine); | 3385 states.AddToNode(store, bailout_id, combine); |
3380 return store; | 3386 return store; |
3381 } | 3387 } |
3382 case Variable::PARAMETER: | 3388 case VariableLocation::PARAMETER: |
3383 case Variable::LOCAL: | 3389 case VariableLocation::LOCAL: |
3384 // Local var, const, or let variable. | 3390 // Local var, const, or let variable. |
3385 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { | 3391 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { |
3386 // Perform an initialization check for legacy const variables. | 3392 // Perform an initialization check for legacy const variables. |
3387 Node* current = environment()->Lookup(variable); | 3393 Node* current = environment()->Lookup(variable); |
3388 if (current->op() != the_hole->op()) { | 3394 if (current->op() != the_hole->op()) { |
3389 value = BuildHoleCheckSilent(current, value, current); | 3395 value = BuildHoleCheckSilent(current, value, current); |
3390 } | 3396 } |
3391 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { | 3397 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { |
3392 // Non-initializing assignment to legacy const is | 3398 // Non-initializing assignment to legacy const is |
3393 // - exception in strict mode. | 3399 // - exception in strict mode. |
(...skipping 18 matching lines...) Expand all Loading... |
3412 Node* current = environment()->Lookup(variable); | 3418 Node* current = environment()->Lookup(variable); |
3413 if (current->op() == the_hole->op()) { | 3419 if (current->op() == the_hole->op()) { |
3414 return BuildThrowReferenceError(variable, bailout_id); | 3420 return BuildThrowReferenceError(variable, bailout_id); |
3415 } else if (value->opcode() == IrOpcode::kPhi) { | 3421 } else if (value->opcode() == IrOpcode::kPhi) { |
3416 BuildHoleCheckThrow(current, variable, value, bailout_id); | 3422 BuildHoleCheckThrow(current, variable, value, bailout_id); |
3417 } | 3423 } |
3418 return BuildThrowConstAssignError(bailout_id); | 3424 return BuildThrowConstAssignError(bailout_id); |
3419 } | 3425 } |
3420 environment()->Bind(variable, value); | 3426 environment()->Bind(variable, value); |
3421 return value; | 3427 return value; |
3422 case Variable::CONTEXT: { | 3428 case VariableLocation::CONTEXT: { |
3423 // Context variable (potentially up the context chain). | 3429 // Context variable (potentially up the context chain). |
3424 int depth = current_scope()->ContextChainLength(variable->scope()); | 3430 int depth = current_scope()->ContextChainLength(variable->scope()); |
3425 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { | 3431 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { |
3426 // Perform an initialization check for legacy const variables. | 3432 // Perform an initialization check for legacy const variables. |
3427 const Operator* op = | 3433 const Operator* op = |
3428 javascript()->LoadContext(depth, variable->index(), false); | 3434 javascript()->LoadContext(depth, variable->index(), false); |
3429 Node* current = NewNode(op, current_context()); | 3435 Node* current = NewNode(op, current_context()); |
3430 value = BuildHoleCheckSilent(current, value, current); | 3436 value = BuildHoleCheckSilent(current, value, current); |
3431 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { | 3437 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { |
3432 // Non-initializing assignment to legacy const is | 3438 // Non-initializing assignment to legacy const is |
(...skipping 13 matching lines...) Expand all Loading... |
3446 // Assignment to const is exception in all modes. | 3452 // Assignment to const is exception in all modes. |
3447 const Operator* op = | 3453 const Operator* op = |
3448 javascript()->LoadContext(depth, variable->index(), false); | 3454 javascript()->LoadContext(depth, variable->index(), false); |
3449 Node* current = NewNode(op, current_context()); | 3455 Node* current = NewNode(op, current_context()); |
3450 BuildHoleCheckThrow(current, variable, value, bailout_id); | 3456 BuildHoleCheckThrow(current, variable, value, bailout_id); |
3451 return BuildThrowConstAssignError(bailout_id); | 3457 return BuildThrowConstAssignError(bailout_id); |
3452 } | 3458 } |
3453 const Operator* op = javascript()->StoreContext(depth, variable->index()); | 3459 const Operator* op = javascript()->StoreContext(depth, variable->index()); |
3454 return NewNode(op, current_context(), value); | 3460 return NewNode(op, current_context(), value); |
3455 } | 3461 } |
3456 case Variable::LOOKUP: { | 3462 case VariableLocation::LOOKUP: { |
3457 // Dynamic lookup of context variable (anywhere in the chain). | 3463 // Dynamic lookup of context variable (anywhere in the chain). |
3458 Node* name = jsgraph()->Constant(variable->name()); | 3464 Node* name = jsgraph()->Constant(variable->name()); |
3459 Node* language = jsgraph()->Constant(language_mode()); | 3465 Node* language = jsgraph()->Constant(language_mode()); |
3460 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for | 3466 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for |
3461 // initializations of const declarations. | 3467 // initializations of const declarations. |
3462 const Operator* op = | 3468 const Operator* op = |
3463 javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4); | 3469 javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4); |
3464 Node* store = NewNode(op, value, current_context(), name, language); | 3470 Node* store = NewNode(op, value, current_context(), name, language); |
3465 PrepareFrameState(store, bailout_id, combine); | 3471 PrepareFrameState(store, bailout_id, combine); |
3466 return store; | 3472 return store; |
(...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4162 // Phi does not exist yet, introduce one. | 4168 // Phi does not exist yet, introduce one. |
4163 value = NewPhi(inputs, value, control); | 4169 value = NewPhi(inputs, value, control); |
4164 value->ReplaceInput(inputs - 1, other); | 4170 value->ReplaceInput(inputs - 1, other); |
4165 } | 4171 } |
4166 return value; | 4172 return value; |
4167 } | 4173 } |
4168 | 4174 |
4169 } // namespace compiler | 4175 } // namespace compiler |
4170 } // namespace internal | 4176 } // namespace internal |
4171 } // namespace v8 | 4177 } // namespace v8 |
OLD | NEW |