| 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 |