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