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/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
9 #include "src/compilation-info.h" | 9 #include "src/compilation-info.h" |
10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
(...skipping 1095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1106 environment()->Bind(variable, value); | 1106 environment()->Bind(variable, value); |
1107 } | 1107 } |
1108 break; | 1108 break; |
1109 case VariableLocation::CONTEXT: | 1109 case VariableLocation::CONTEXT: |
1110 if (variable->binding_needs_init()) { | 1110 if (variable->binding_needs_init()) { |
1111 Node* value = jsgraph()->TheHoleConstant(); | 1111 Node* value = jsgraph()->TheHoleConstant(); |
1112 const Operator* op = javascript()->StoreContext(0, variable->index()); | 1112 const Operator* op = javascript()->StoreContext(0, variable->index()); |
1113 NewNode(op, current_context(), value); | 1113 NewNode(op, current_context(), value); |
1114 } | 1114 } |
1115 break; | 1115 break; |
1116 case VariableLocation::LOOKUP: { | 1116 case VariableLocation::LOOKUP: |
1117 DCHECK(!variable->binding_needs_init()); | |
1118 Node* name = jsgraph()->Constant(variable->name()); | |
1119 const Operator* op = javascript()->CallRuntime(Runtime::kDeclareEvalVar); | |
1120 Node* store = NewNode(op, name); | |
1121 PrepareFrameState(store, decl->proxy()->id()); | |
1122 break; | |
1123 } | |
1124 case VariableLocation::MODULE: | 1117 case VariableLocation::MODULE: |
1125 UNREACHABLE(); | 1118 UNREACHABLE(); |
1126 } | 1119 } |
1127 } | 1120 } |
1128 | 1121 |
1129 | 1122 |
1130 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 1123 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
1131 Variable* variable = decl->proxy()->var(); | 1124 Variable* variable = decl->proxy()->var(); |
1132 switch (variable->location()) { | 1125 switch (variable->location()) { |
1133 case VariableLocation::UNALLOCATED: { | 1126 case VariableLocation::UNALLOCATED: { |
(...skipping 15 matching lines...) Expand all Loading... |
1149 environment()->Bind(variable, value); | 1142 environment()->Bind(variable, value); |
1150 break; | 1143 break; |
1151 } | 1144 } |
1152 case VariableLocation::CONTEXT: { | 1145 case VariableLocation::CONTEXT: { |
1153 VisitForValue(decl->fun()); | 1146 VisitForValue(decl->fun()); |
1154 Node* value = environment()->Pop(); | 1147 Node* value = environment()->Pop(); |
1155 const Operator* op = javascript()->StoreContext(0, variable->index()); | 1148 const Operator* op = javascript()->StoreContext(0, variable->index()); |
1156 NewNode(op, current_context(), value); | 1149 NewNode(op, current_context(), value); |
1157 break; | 1150 break; |
1158 } | 1151 } |
1159 case VariableLocation::LOOKUP: { | 1152 case VariableLocation::LOOKUP: |
1160 VisitForValue(decl->fun()); | |
1161 Node* value = environment()->Pop(); | |
1162 Node* name = jsgraph()->Constant(variable->name()); | |
1163 const Operator* op = | |
1164 javascript()->CallRuntime(Runtime::kDeclareEvalFunction); | |
1165 Node* store = NewNode(op, name, value); | |
1166 PrepareFrameState(store, decl->proxy()->id()); | |
1167 break; | |
1168 } | |
1169 case VariableLocation::MODULE: | 1153 case VariableLocation::MODULE: |
1170 UNREACHABLE(); | 1154 UNREACHABLE(); |
1171 } | 1155 } |
1172 } | 1156 } |
1173 | 1157 |
1174 | 1158 |
1175 void AstGraphBuilder::VisitBlock(Block* stmt) { | 1159 void AstGraphBuilder::VisitBlock(Block* stmt) { |
1176 BlockBuilder block(this); | 1160 BlockBuilder block(this); |
1177 ControlScopeForBreakable scope(this, stmt, &block); | 1161 ControlScopeForBreakable scope(this, stmt, &block); |
1178 if (stmt->labels() != nullptr) block.BeginBlock(); | 1162 if (stmt->labels() != nullptr) block.BeginBlock(); |
(...skipping 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2266 break; | 2250 break; |
2267 } | 2251 } |
2268 } | 2252 } |
2269 ast_context()->ProduceValue(expr, value); | 2253 ast_context()->ProduceValue(expr, value); |
2270 } | 2254 } |
2271 | 2255 |
2272 | 2256 |
2273 void AstGraphBuilder::VisitCall(Call* expr) { | 2257 void AstGraphBuilder::VisitCall(Call* expr) { |
2274 Expression* callee = expr->expression(); | 2258 Expression* callee = expr->expression(); |
2275 Call::CallType call_type = expr->GetCallType(); | 2259 Call::CallType call_type = expr->GetCallType(); |
| 2260 CHECK(!expr->is_possibly_eval()); |
2276 | 2261 |
2277 // Prepare the callee and the receiver to the function call. This depends on | 2262 // Prepare the callee and the receiver to the function call. This depends on |
2278 // the semantics of the underlying call type. | 2263 // the semantics of the underlying call type. |
2279 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny; | 2264 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny; |
2280 Node* receiver_value = nullptr; | 2265 Node* receiver_value = nullptr; |
2281 Node* callee_value = nullptr; | 2266 Node* callee_value = nullptr; |
2282 if (expr->is_possibly_eval()) { | 2267 switch (call_type) { |
2283 if (callee->AsVariableProxy()->var()->IsLookupSlot()) { | 2268 case Call::GLOBAL_CALL: { |
2284 Variable* variable = callee->AsVariableProxy()->var(); | 2269 VariableProxy* proxy = callee->AsVariableProxy(); |
2285 Node* name = jsgraph()->Constant(variable->name()); | 2270 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
2286 const Operator* op = | 2271 PrepareEagerCheckpoint(BeforeId(proxy)); |
2287 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall); | 2272 callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(), |
2288 Node* pair = NewNode(op, name); | 2273 pair, OutputFrameStateCombine::Push()); |
2289 callee_value = NewNode(common()->Projection(0), pair); | 2274 receiver_hint = ConvertReceiverMode::kNullOrUndefined; |
2290 receiver_value = NewNode(common()->Projection(1), pair); | 2275 receiver_value = jsgraph()->UndefinedConstant(); |
2291 PrepareFrameState(pair, expr->LookupId(), | 2276 break; |
2292 OutputFrameStateCombine::Push(2)); | 2277 } |
2293 } else { | 2278 case Call::NAMED_PROPERTY_CALL: { |
| 2279 Property* property = callee->AsProperty(); |
| 2280 VectorSlotPair feedback = |
| 2281 CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
| 2282 VisitForValue(property->obj()); |
| 2283 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| 2284 Node* object = environment()->Top(); |
| 2285 callee_value = BuildNamedLoad(object, name, feedback); |
| 2286 PrepareFrameState(callee_value, property->LoadId(), |
| 2287 OutputFrameStateCombine::Push()); |
| 2288 // Note that a property call requires the receiver to be wrapped into |
| 2289 // an object for sloppy callees. However the receiver is guaranteed |
| 2290 // not to be null or undefined at this point. |
| 2291 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined; |
| 2292 receiver_value = environment()->Pop(); |
| 2293 break; |
| 2294 } |
| 2295 case Call::KEYED_PROPERTY_CALL: { |
| 2296 Property* property = callee->AsProperty(); |
| 2297 VectorSlotPair feedback = |
| 2298 CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
| 2299 VisitForValue(property->obj()); |
| 2300 VisitForValue(property->key()); |
| 2301 Node* key = environment()->Pop(); |
| 2302 Node* object = environment()->Top(); |
| 2303 callee_value = BuildKeyedLoad(object, key, feedback); |
| 2304 PrepareFrameState(callee_value, property->LoadId(), |
| 2305 OutputFrameStateCombine::Push()); |
| 2306 // Note that a property call requires the receiver to be wrapped into |
| 2307 // an object for sloppy callees. However the receiver is guaranteed |
| 2308 // not to be null or undefined at this point. |
| 2309 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined; |
| 2310 receiver_value = environment()->Pop(); |
| 2311 break; |
| 2312 } |
| 2313 case Call::NAMED_SUPER_PROPERTY_CALL: { |
| 2314 Property* property = callee->AsProperty(); |
| 2315 SuperPropertyReference* super_ref = |
| 2316 property->obj()->AsSuperPropertyReference(); |
| 2317 VisitForValue(super_ref->home_object()); |
| 2318 VisitForValue(super_ref->this_var()); |
| 2319 Node* home = environment()->Peek(1); |
| 2320 Node* object = environment()->Top(); |
| 2321 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| 2322 callee_value = BuildNamedSuperLoad(object, home, name, VectorSlotPair()); |
| 2323 PrepareFrameState(callee_value, property->LoadId(), |
| 2324 OutputFrameStateCombine::Push()); |
| 2325 // Note that a property call requires the receiver to be wrapped into |
| 2326 // an object for sloppy callees. Since the receiver is not the target of |
| 2327 // the load, it could very well be null or undefined at this point. |
| 2328 receiver_value = environment()->Pop(); |
| 2329 environment()->Drop(1); |
| 2330 break; |
| 2331 } |
| 2332 case Call::KEYED_SUPER_PROPERTY_CALL: { |
| 2333 Property* property = callee->AsProperty(); |
| 2334 SuperPropertyReference* super_ref = |
| 2335 property->obj()->AsSuperPropertyReference(); |
| 2336 VisitForValue(super_ref->home_object()); |
| 2337 VisitForValue(super_ref->this_var()); |
| 2338 environment()->Push(environment()->Top()); // Duplicate this_var. |
| 2339 environment()->Push(environment()->Peek(2)); // Duplicate home_obj. |
| 2340 VisitForValue(property->key()); |
| 2341 Node* key = environment()->Pop(); |
| 2342 Node* home = environment()->Pop(); |
| 2343 Node* object = environment()->Pop(); |
| 2344 callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair()); |
| 2345 PrepareFrameState(callee_value, property->LoadId(), |
| 2346 OutputFrameStateCombine::Push()); |
| 2347 // Note that a property call requires the receiver to be wrapped into |
| 2348 // an object for sloppy callees. Since the receiver is not the target of |
| 2349 // the load, it could very well be null or undefined at this point. |
| 2350 receiver_value = environment()->Pop(); |
| 2351 environment()->Drop(1); |
| 2352 break; |
| 2353 } |
| 2354 case Call::SUPER_CALL: |
| 2355 return VisitCallSuper(expr); |
| 2356 case Call::OTHER_CALL: |
2294 VisitForValue(callee); | 2357 VisitForValue(callee); |
2295 callee_value = environment()->Pop(); | 2358 callee_value = environment()->Pop(); |
2296 receiver_hint = ConvertReceiverMode::kNullOrUndefined; | 2359 receiver_hint = ConvertReceiverMode::kNullOrUndefined; |
2297 receiver_value = jsgraph()->UndefinedConstant(); | 2360 receiver_value = jsgraph()->UndefinedConstant(); |
2298 } | 2361 break; |
2299 } else { | 2362 case Call::WITH_CALL: |
2300 switch (call_type) { | 2363 UNREACHABLE(); |
2301 case Call::GLOBAL_CALL: { | |
2302 VariableProxy* proxy = callee->AsVariableProxy(); | |
2303 VectorSlotPair pair = | |
2304 CreateVectorSlotPair(proxy->VariableFeedbackSlot()); | |
2305 PrepareEagerCheckpoint(BeforeId(proxy)); | |
2306 callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(), | |
2307 pair, OutputFrameStateCombine::Push()); | |
2308 receiver_hint = ConvertReceiverMode::kNullOrUndefined; | |
2309 receiver_value = jsgraph()->UndefinedConstant(); | |
2310 break; | |
2311 } | |
2312 case Call::WITH_CALL: { | |
2313 Variable* variable = callee->AsVariableProxy()->var(); | |
2314 Node* name = jsgraph()->Constant(variable->name()); | |
2315 const Operator* op = | |
2316 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall); | |
2317 Node* pair = NewNode(op, name); | |
2318 callee_value = NewNode(common()->Projection(0), pair); | |
2319 receiver_value = NewNode(common()->Projection(1), pair); | |
2320 PrepareFrameState(pair, expr->LookupId(), | |
2321 OutputFrameStateCombine::Push(2)); | |
2322 break; | |
2323 } | |
2324 case Call::NAMED_PROPERTY_CALL: { | |
2325 Property* property = callee->AsProperty(); | |
2326 VectorSlotPair feedback = | |
2327 CreateVectorSlotPair(property->PropertyFeedbackSlot()); | |
2328 VisitForValue(property->obj()); | |
2329 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); | |
2330 Node* object = environment()->Top(); | |
2331 callee_value = BuildNamedLoad(object, name, feedback); | |
2332 PrepareFrameState(callee_value, property->LoadId(), | |
2333 OutputFrameStateCombine::Push()); | |
2334 // Note that a property call requires the receiver to be wrapped into | |
2335 // an object for sloppy callees. However the receiver is guaranteed | |
2336 // not to be null or undefined at this point. | |
2337 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined; | |
2338 receiver_value = environment()->Pop(); | |
2339 break; | |
2340 } | |
2341 case Call::KEYED_PROPERTY_CALL: { | |
2342 Property* property = callee->AsProperty(); | |
2343 VectorSlotPair feedback = | |
2344 CreateVectorSlotPair(property->PropertyFeedbackSlot()); | |
2345 VisitForValue(property->obj()); | |
2346 VisitForValue(property->key()); | |
2347 Node* key = environment()->Pop(); | |
2348 Node* object = environment()->Top(); | |
2349 callee_value = BuildKeyedLoad(object, key, feedback); | |
2350 PrepareFrameState(callee_value, property->LoadId(), | |
2351 OutputFrameStateCombine::Push()); | |
2352 // Note that a property call requires the receiver to be wrapped into | |
2353 // an object for sloppy callees. However the receiver is guaranteed | |
2354 // not to be null or undefined at this point. | |
2355 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined; | |
2356 receiver_value = environment()->Pop(); | |
2357 break; | |
2358 } | |
2359 case Call::NAMED_SUPER_PROPERTY_CALL: { | |
2360 Property* property = callee->AsProperty(); | |
2361 SuperPropertyReference* super_ref = | |
2362 property->obj()->AsSuperPropertyReference(); | |
2363 VisitForValue(super_ref->home_object()); | |
2364 VisitForValue(super_ref->this_var()); | |
2365 Node* home = environment()->Peek(1); | |
2366 Node* object = environment()->Top(); | |
2367 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); | |
2368 callee_value = | |
2369 BuildNamedSuperLoad(object, home, name, VectorSlotPair()); | |
2370 PrepareFrameState(callee_value, property->LoadId(), | |
2371 OutputFrameStateCombine::Push()); | |
2372 // Note that a property call requires the receiver to be wrapped into | |
2373 // an object for sloppy callees. Since the receiver is not the target of | |
2374 // the load, it could very well be null or undefined at this point. | |
2375 receiver_value = environment()->Pop(); | |
2376 environment()->Drop(1); | |
2377 break; | |
2378 } | |
2379 case Call::KEYED_SUPER_PROPERTY_CALL: { | |
2380 Property* property = callee->AsProperty(); | |
2381 SuperPropertyReference* super_ref = | |
2382 property->obj()->AsSuperPropertyReference(); | |
2383 VisitForValue(super_ref->home_object()); | |
2384 VisitForValue(super_ref->this_var()); | |
2385 environment()->Push(environment()->Top()); // Duplicate this_var. | |
2386 environment()->Push(environment()->Peek(2)); // Duplicate home_obj. | |
2387 VisitForValue(property->key()); | |
2388 Node* key = environment()->Pop(); | |
2389 Node* home = environment()->Pop(); | |
2390 Node* object = environment()->Pop(); | |
2391 callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair()); | |
2392 PrepareFrameState(callee_value, property->LoadId(), | |
2393 OutputFrameStateCombine::Push()); | |
2394 // Note that a property call requires the receiver to be wrapped into | |
2395 // an object for sloppy callees. Since the receiver is not the target of | |
2396 // the load, it could very well be null or undefined at this point. | |
2397 receiver_value = environment()->Pop(); | |
2398 environment()->Drop(1); | |
2399 break; | |
2400 } | |
2401 case Call::SUPER_CALL: | |
2402 return VisitCallSuper(expr); | |
2403 case Call::OTHER_CALL: | |
2404 VisitForValue(callee); | |
2405 callee_value = environment()->Pop(); | |
2406 receiver_hint = ConvertReceiverMode::kNullOrUndefined; | |
2407 receiver_value = jsgraph()->UndefinedConstant(); | |
2408 break; | |
2409 } | |
2410 } | 2364 } |
2411 | 2365 |
2412 // The callee and the receiver both have to be pushed onto the operand stack | 2366 // The callee and the receiver both have to be pushed onto the operand stack |
2413 // before arguments are being evaluated. | 2367 // before arguments are being evaluated. |
2414 environment()->Push(callee_value); | 2368 environment()->Push(callee_value); |
2415 environment()->Push(receiver_value); | 2369 environment()->Push(receiver_value); |
2416 | 2370 |
2417 // Evaluate all arguments to the function call, | 2371 // Evaluate all arguments to the function call, |
2418 ZoneList<Expression*>* args = expr->arguments(); | 2372 ZoneList<Expression*>* args = expr->arguments(); |
2419 VisitForValues(args); | 2373 VisitForValues(args); |
(...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3068 VectorSlotPair AstGraphBuilder::CreateVectorSlotPair( | 3022 VectorSlotPair AstGraphBuilder::CreateVectorSlotPair( |
3069 FeedbackVectorSlot slot) const { | 3023 FeedbackVectorSlot slot) const { |
3070 return VectorSlotPair(handle(info()->closure()->feedback_vector()), slot); | 3024 return VectorSlotPair(handle(info()->closure()->feedback_vector()), slot); |
3071 } | 3025 } |
3072 | 3026 |
3073 | 3027 |
3074 void AstGraphBuilder::VisitRewritableExpression(RewritableExpression* node) { | 3028 void AstGraphBuilder::VisitRewritableExpression(RewritableExpression* node) { |
3075 Visit(node->expression()); | 3029 Visit(node->expression()); |
3076 } | 3030 } |
3077 | 3031 |
3078 | |
3079 namespace { | |
3080 | |
3081 // Limit of context chain length to which inline check is possible. | |
3082 const int kMaxCheckDepth = 30; | |
3083 | |
3084 // Sentinel for {TryLoadDynamicVariable} disabling inline checks. | |
3085 const uint32_t kFullCheckRequired = -1; | |
3086 | |
3087 } // namespace | |
3088 | |
3089 | |
3090 uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) { | |
3091 DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode()); | |
3092 uint32_t check_depths = 0; | |
3093 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) { | |
3094 if (!s->NeedsContext()) continue; | |
3095 if (!s->calls_sloppy_eval()) continue; | |
3096 int depth = current_scope()->ContextChainLength(s); | |
3097 if (depth > kMaxCheckDepth) return kFullCheckRequired; | |
3098 check_depths |= 1 << depth; | |
3099 } | |
3100 return check_depths; | |
3101 } | |
3102 | |
3103 | |
3104 uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) { | |
3105 DCHECK_EQ(DYNAMIC_LOCAL, variable->mode()); | |
3106 uint32_t check_depths = 0; | |
3107 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) { | |
3108 if (!s->NeedsContext()) continue; | |
3109 if (!s->calls_sloppy_eval() && s != variable->scope()) continue; | |
3110 int depth = current_scope()->ContextChainLength(s); | |
3111 if (depth > kMaxCheckDepth) return kFullCheckRequired; | |
3112 check_depths |= 1 << depth; | |
3113 if (s == variable->scope()) break; | |
3114 } | |
3115 return check_depths; | |
3116 } | |
3117 | |
3118 float AstGraphBuilder::ComputeCallFrequency(FeedbackVectorSlot slot) const { | 3032 float AstGraphBuilder::ComputeCallFrequency(FeedbackVectorSlot slot) const { |
3119 if (slot.IsInvalid()) return 0.0f; | 3033 if (slot.IsInvalid()) return 0.0f; |
3120 Handle<TypeFeedbackVector> feedback_vector( | 3034 Handle<TypeFeedbackVector> feedback_vector( |
3121 info()->closure()->feedback_vector(), isolate()); | 3035 info()->closure()->feedback_vector(), isolate()); |
3122 CallICNexus nexus(feedback_vector, slot); | 3036 CallICNexus nexus(feedback_vector, slot); |
3123 return nexus.ComputeCallFrequency() * invocation_frequency_; | 3037 return nexus.ComputeCallFrequency() * invocation_frequency_; |
3124 } | 3038 } |
3125 | 3039 |
3126 Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) { | 3040 Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) { |
3127 DCHECK(environment()->stack_height() >= arity); | 3041 DCHECK(environment()->stack_height() >= arity); |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3367 Node* value = NewNode(op, current_context()); | 3281 Node* value = NewNode(op, current_context()); |
3368 // TODO(titzer): initialization checks are redundant for already | 3282 // TODO(titzer): initialization checks are redundant for already |
3369 // initialized immutable context loads, but only specialization knows. | 3283 // initialized immutable context loads, but only specialization knows. |
3370 // Maybe specializer should be a parameter to the graph builder? | 3284 // Maybe specializer should be a parameter to the graph builder? |
3371 if (variable->binding_needs_init()) { | 3285 if (variable->binding_needs_init()) { |
3372 // Perform check for uninitialized let/const variables. | 3286 // Perform check for uninitialized let/const variables. |
3373 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id); | 3287 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id); |
3374 } | 3288 } |
3375 return value; | 3289 return value; |
3376 } | 3290 } |
3377 case VariableLocation::LOOKUP: { | 3291 case VariableLocation::LOOKUP: |
3378 // Dynamic lookup of context variable (anywhere in the chain). | |
3379 Handle<String> name = variable->name(); | |
3380 if (Node* node = TryLoadDynamicVariable(variable, name, bailout_id, | |
3381 feedback, combine, typeof_mode)) { | |
3382 return node; | |
3383 } | |
3384 Node* value = BuildDynamicLoad(name, typeof_mode); | |
3385 PrepareFrameState(value, bailout_id, combine); | |
3386 return value; | |
3387 } | |
3388 case VariableLocation::MODULE: | 3292 case VariableLocation::MODULE: |
3389 UNREACHABLE(); | 3293 UNREACHABLE(); |
3390 } | 3294 } |
3391 UNREACHABLE(); | 3295 UNREACHABLE(); |
3392 return nullptr; | 3296 return nullptr; |
3393 } | 3297 } |
3394 | 3298 |
3395 | 3299 |
3396 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, | 3300 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, |
3397 BailoutId bailout_id, | 3301 BailoutId bailout_id, |
3398 OutputFrameStateCombine combine) { | 3302 OutputFrameStateCombine combine) { |
3399 switch (variable->location()) { | 3303 switch (variable->location()) { |
3400 case VariableLocation::UNALLOCATED: { | 3304 case VariableLocation::UNALLOCATED: { |
3401 // Global var, const, or let variable. | 3305 // Global var, const, or let variable. |
3402 Node* global = BuildLoadGlobalObject(); | 3306 Node* global = BuildLoadGlobalObject(); |
3403 Node* name = jsgraph()->Constant(variable->name()); | 3307 Node* name = jsgraph()->Constant(variable->name()); |
3404 const Operator* op = javascript()->DeleteProperty(language_mode()); | 3308 const Operator* op = javascript()->DeleteProperty(language_mode()); |
3405 Node* result = NewNode(op, global, name); | 3309 Node* result = NewNode(op, global, name); |
3406 PrepareFrameState(result, bailout_id, combine); | 3310 PrepareFrameState(result, bailout_id, combine); |
3407 return result; | 3311 return result; |
3408 } | 3312 } |
3409 case VariableLocation::PARAMETER: | 3313 case VariableLocation::PARAMETER: |
3410 case VariableLocation::LOCAL: | 3314 case VariableLocation::LOCAL: |
3411 case VariableLocation::CONTEXT: { | 3315 case VariableLocation::CONTEXT: { |
3412 // Local var, const, or let variable or context variable. | 3316 // Local var, const, or let variable or context variable. |
3413 return jsgraph()->BooleanConstant(variable->is_this()); | 3317 return jsgraph()->BooleanConstant(variable->is_this()); |
3414 } | 3318 } |
3415 case VariableLocation::LOOKUP: { | 3319 case VariableLocation::LOOKUP: |
3416 // Dynamic lookup of context variable (anywhere in the chain). | |
3417 Node* name = jsgraph()->Constant(variable->name()); | |
3418 const Operator* op = | |
3419 javascript()->CallRuntime(Runtime::kDeleteLookupSlot); | |
3420 Node* result = NewNode(op, name); | |
3421 PrepareFrameState(result, bailout_id, combine); | |
3422 return result; | |
3423 } | |
3424 case VariableLocation::MODULE: | 3320 case VariableLocation::MODULE: |
3425 UNREACHABLE(); | 3321 UNREACHABLE(); |
3426 } | 3322 } |
3427 UNREACHABLE(); | 3323 UNREACHABLE(); |
3428 return nullptr; | 3324 return nullptr; |
3429 } | 3325 } |
3430 | 3326 |
3431 Node* AstGraphBuilder::BuildVariableAssignment( | 3327 Node* AstGraphBuilder::BuildVariableAssignment( |
3432 Variable* variable, Node* value, Token::Value op, | 3328 Variable* variable, Node* value, Token::Value op, |
3433 const VectorSlotPair& feedback, BailoutId bailout_id, | 3329 const VectorSlotPair& feedback, BailoutId bailout_id, |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3527 javascript()->LoadContext(depth, variable->index(), false); | 3423 javascript()->LoadContext(depth, variable->index(), false); |
3528 Node* current = NewNode(op, current_context()); | 3424 Node* current = NewNode(op, current_context()); |
3529 BuildHoleCheckThenThrow(current, variable, value, bailout_id); | 3425 BuildHoleCheckThenThrow(current, variable, value, bailout_id); |
3530 } | 3426 } |
3531 // Assignment to const is exception in all modes. | 3427 // Assignment to const is exception in all modes. |
3532 return BuildThrowConstAssignError(bailout_id); | 3428 return BuildThrowConstAssignError(bailout_id); |
3533 } | 3429 } |
3534 const Operator* op = javascript()->StoreContext(depth, variable->index()); | 3430 const Operator* op = javascript()->StoreContext(depth, variable->index()); |
3535 return NewNode(op, current_context(), value); | 3431 return NewNode(op, current_context(), value); |
3536 } | 3432 } |
3537 case VariableLocation::LOOKUP: { | 3433 case VariableLocation::LOOKUP: |
3538 // Dynamic lookup of context variable (anywhere in the chain). | |
3539 Handle<Name> name = variable->name(); | |
3540 Node* store = BuildDynamicStore(name, value); | |
3541 PrepareFrameState(store, bailout_id, combine); | |
3542 return store; | |
3543 } | |
3544 case VariableLocation::MODULE: | 3434 case VariableLocation::MODULE: |
3545 UNREACHABLE(); | 3435 UNREACHABLE(); |
3546 } | 3436 } |
3547 UNREACHABLE(); | 3437 UNREACHABLE(); |
3548 return nullptr; | 3438 return nullptr; |
3549 } | 3439 } |
3550 | 3440 |
3551 | 3441 |
3552 Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key, | 3442 Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key, |
3553 const VectorSlotPair& feedback) { | 3443 const VectorSlotPair& feedback) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3635 | 3525 |
3636 | 3526 |
3637 Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value, | 3527 Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value, |
3638 const VectorSlotPair& feedback) { | 3528 const VectorSlotPair& feedback) { |
3639 const Operator* op = | 3529 const Operator* op = |
3640 javascript()->StoreGlobal(language_mode(), name, feedback); | 3530 javascript()->StoreGlobal(language_mode(), name, feedback); |
3641 Node* node = NewNode(op, value, GetFunctionClosure()); | 3531 Node* node = NewNode(op, value, GetFunctionClosure()); |
3642 return node; | 3532 return node; |
3643 } | 3533 } |
3644 | 3534 |
3645 | |
3646 Node* AstGraphBuilder::BuildDynamicLoad(Handle<Name> name, | |
3647 TypeofMode typeof_mode) { | |
3648 Node* name_node = jsgraph()->Constant(name); | |
3649 const Operator* op = | |
3650 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF | |
3651 ? Runtime::kLoadLookupSlot | |
3652 : Runtime::kLoadLookupSlotInsideTypeof); | |
3653 Node* node = NewNode(op, name_node); | |
3654 return node; | |
3655 } | |
3656 | |
3657 | |
3658 Node* AstGraphBuilder::BuildDynamicStore(Handle<Name> name, Node* value) { | |
3659 Node* name_node = jsgraph()->Constant(name); | |
3660 const Operator* op = javascript()->CallRuntime( | |
3661 is_strict(language_mode()) ? Runtime::kStoreLookupSlot_Strict | |
3662 : Runtime::kStoreLookupSlot_Sloppy); | |
3663 Node* node = NewNode(op, name_node, value); | |
3664 return node; | |
3665 } | |
3666 | |
3667 | |
3668 Node* AstGraphBuilder::BuildLoadGlobalObject() { | 3535 Node* AstGraphBuilder::BuildLoadGlobalObject() { |
3669 return BuildLoadNativeContextField(Context::EXTENSION_INDEX); | 3536 return BuildLoadNativeContextField(Context::EXTENSION_INDEX); |
3670 } | 3537 } |
3671 | 3538 |
3672 | 3539 |
3673 Node* AstGraphBuilder::BuildLoadNativeContextField(int index) { | 3540 Node* AstGraphBuilder::BuildLoadNativeContextField(int index) { |
3674 const Operator* op = | 3541 const Operator* op = |
3675 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true); | 3542 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true); |
3676 Node* native_context = NewNode(op, current_context()); | 3543 Node* native_context = NewNode(op, current_context()); |
3677 return NewNode(javascript()->LoadContext(0, index, true), native_context); | 3544 return NewNode(javascript()->LoadContext(0, index, true), native_context); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3844 } | 3711 } |
3845 | 3712 |
3846 | 3713 |
3847 Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) { | 3714 Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) { |
3848 // Optimize global constants like "undefined", "Infinity", and "NaN". | 3715 // Optimize global constants like "undefined", "Infinity", and "NaN". |
3849 Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name); | 3716 Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name); |
3850 if (!constant_value.is_null()) return jsgraph()->Constant(constant_value); | 3717 if (!constant_value.is_null()) return jsgraph()->Constant(constant_value); |
3851 return nullptr; | 3718 return nullptr; |
3852 } | 3719 } |
3853 | 3720 |
3854 Node* AstGraphBuilder::TryLoadDynamicVariable(Variable* variable, | |
3855 Handle<String> name, | |
3856 BailoutId bailout_id, | |
3857 const VectorSlotPair& feedback, | |
3858 OutputFrameStateCombine combine, | |
3859 TypeofMode typeof_mode) { | |
3860 VariableMode mode = variable->mode(); | |
3861 | |
3862 if (mode == DYNAMIC_GLOBAL) { | |
3863 uint32_t bitset = ComputeBitsetForDynamicGlobal(variable); | |
3864 if (bitset == kFullCheckRequired) return nullptr; | |
3865 | |
3866 // We are using two blocks to model fast and slow cases. | |
3867 BlockBuilder fast_block(this); | |
3868 BlockBuilder slow_block(this); | |
3869 environment()->Push(jsgraph()->TheHoleConstant()); | |
3870 slow_block.BeginBlock(); | |
3871 environment()->Pop(); | |
3872 fast_block.BeginBlock(); | |
3873 | |
3874 // Perform checks whether the fast mode applies, by looking for any | |
3875 // extension object which might shadow the optimistic declaration. | |
3876 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) { | |
3877 if ((bitset & 1) == 0) continue; | |
3878 Node* load = NewNode( | |
3879 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false), | |
3880 current_context()); | |
3881 Node* check = | |
3882 NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), load, | |
3883 jsgraph()->TheHoleConstant()); | |
3884 fast_block.BreakUnless(check, BranchHint::kTrue); | |
3885 } | |
3886 | |
3887 // Fast case, because variable is not shadowed. | |
3888 if (Node* constant = TryLoadGlobalConstant(name)) { | |
3889 environment()->Push(constant); | |
3890 } else { | |
3891 // Perform global slot load. | |
3892 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode); | |
3893 PrepareFrameState(fast, bailout_id, combine); | |
3894 environment()->Push(fast); | |
3895 } | |
3896 slow_block.Break(); | |
3897 environment()->Pop(); | |
3898 fast_block.EndBlock(); | |
3899 | |
3900 // Slow case, because variable potentially shadowed. Perform dynamic lookup. | |
3901 Node* slow = BuildDynamicLoad(name, typeof_mode); | |
3902 PrepareFrameState(slow, bailout_id, combine); | |
3903 environment()->Push(slow); | |
3904 slow_block.EndBlock(); | |
3905 | |
3906 return environment()->Pop(); | |
3907 } | |
3908 | |
3909 if (mode == DYNAMIC_LOCAL) { | |
3910 uint32_t bitset = ComputeBitsetForDynamicContext(variable); | |
3911 if (bitset == kFullCheckRequired) return nullptr; | |
3912 | |
3913 // We are using two blocks to model fast and slow cases. | |
3914 BlockBuilder fast_block(this); | |
3915 BlockBuilder slow_block(this); | |
3916 environment()->Push(jsgraph()->TheHoleConstant()); | |
3917 slow_block.BeginBlock(); | |
3918 environment()->Pop(); | |
3919 fast_block.BeginBlock(); | |
3920 | |
3921 // Perform checks whether the fast mode applies, by looking for any | |
3922 // extension object which might shadow the optimistic declaration. | |
3923 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) { | |
3924 if ((bitset & 1) == 0) continue; | |
3925 Node* load = NewNode( | |
3926 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false), | |
3927 current_context()); | |
3928 Node* check = | |
3929 NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), load, | |
3930 jsgraph()->TheHoleConstant()); | |
3931 fast_block.BreakUnless(check, BranchHint::kTrue); | |
3932 } | |
3933 | |
3934 // Fast case, because variable is not shadowed. Perform context slot load. | |
3935 Variable* local = variable->local_if_not_shadowed(); | |
3936 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context. | |
3937 Node* fast = | |
3938 BuildVariableLoad(local, bailout_id, feedback, combine, typeof_mode); | |
3939 environment()->Push(fast); | |
3940 slow_block.Break(); | |
3941 environment()->Pop(); | |
3942 fast_block.EndBlock(); | |
3943 | |
3944 // Slow case, because variable potentially shadowed. Perform dynamic lookup. | |
3945 Node* slow = BuildDynamicLoad(name, typeof_mode); | |
3946 PrepareFrameState(slow, bailout_id, combine); | |
3947 environment()->Push(slow); | |
3948 slow_block.EndBlock(); | |
3949 | |
3950 return environment()->Pop(); | |
3951 } | |
3952 | |
3953 return nullptr; | |
3954 } | |
3955 | |
3956 | |
3957 Node* AstGraphBuilder::TryFastToBoolean(Node* input) { | 3721 Node* AstGraphBuilder::TryFastToBoolean(Node* input) { |
3958 switch (input->opcode()) { | 3722 switch (input->opcode()) { |
3959 case IrOpcode::kNumberConstant: { | 3723 case IrOpcode::kNumberConstant: { |
3960 NumberMatcher m(input); | 3724 NumberMatcher m(input); |
3961 return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN()); | 3725 return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN()); |
3962 } | 3726 } |
3963 case IrOpcode::kHeapConstant: { | 3727 case IrOpcode::kHeapConstant: { |
3964 Handle<HeapObject> object = HeapObjectMatcher(input).Value(); | 3728 Handle<HeapObject> object = HeapObjectMatcher(input).Value(); |
3965 return jsgraph_->BooleanConstant(object->BooleanValue()); | 3729 return jsgraph_->BooleanConstant(object->BooleanValue()); |
3966 } | 3730 } |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4368 TypeHintAnalysis* type_hint_analysis, SourcePositionTable* source_positions, | 4132 TypeHintAnalysis* type_hint_analysis, SourcePositionTable* source_positions, |
4369 int inlining_id) | 4133 int inlining_id) |
4370 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency, | 4134 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency, |
4371 loop_assignment, type_hint_analysis), | 4135 loop_assignment, type_hint_analysis), |
4372 source_positions_(source_positions), | 4136 source_positions_(source_positions), |
4373 start_position_(info->shared_info()->start_position(), inlining_id) {} | 4137 start_position_(info->shared_info()->start_position(), inlining_id) {} |
4374 | 4138 |
4375 } // namespace compiler | 4139 } // namespace compiler |
4376 } // namespace internal | 4140 } // namespace internal |
4377 } // namespace v8 | 4141 } // namespace v8 |
OLD | NEW |