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

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 1884183002: First version of the new generators implementation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecode-register-allocator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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/interpreter/bytecode-generator.h" 5 #include "src/interpreter/bytecode-generator.h"
6 6
7 #include "src/ast/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/compiler.h" 8 #include "src/compiler.h"
9 #include "src/interpreter/bytecode-register-allocator.h" 9 #include "src/interpreter/bytecode-register-allocator.h"
10 #include "src/interpreter/control-flow-builders.h" 10 #include "src/interpreter/control-flow-builders.h"
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 : isolate_(isolate), 558 : isolate_(isolate),
559 zone_(zone), 559 zone_(zone),
560 builder_(nullptr), 560 builder_(nullptr),
561 info_(nullptr), 561 info_(nullptr),
562 scope_(nullptr), 562 scope_(nullptr),
563 globals_(0, zone), 563 globals_(0, zone),
564 execution_control_(nullptr), 564 execution_control_(nullptr),
565 execution_context_(nullptr), 565 execution_context_(nullptr),
566 execution_result_(nullptr), 566 execution_result_(nullptr),
567 register_allocator_(nullptr), 567 register_allocator_(nullptr),
568 generator_resume_points_(0, zone),
568 try_catch_nesting_level_(0), 569 try_catch_nesting_level_(0),
569 try_finally_nesting_level_(0) { 570 try_finally_nesting_level_(0),
571 generator_yields_seen_(0) {
570 InitializeAstVisitor(isolate); 572 InitializeAstVisitor(isolate);
571 } 573 }
572 574
573 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { 575 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
574 set_info(info); 576 set_info(info);
575 set_scope(info->scope()); 577 set_scope(info->scope());
576 578
577 // Initialize bytecode array builder. 579 // Initialize bytecode array builder.
578 set_builder(new (zone()) BytecodeArrayBuilder( 580 set_builder(new (zone()) BytecodeArrayBuilder(
579 isolate(), zone(), info->num_parameters_including_this(), 581 isolate(), zone(), info->num_parameters_including_this(),
580 scope()->MaxNestedContextChainLength(), scope()->num_stack_slots(), 582 scope()->MaxNestedContextChainLength(), scope()->num_stack_slots(),
581 info->literal())); 583 info->literal()));
582 584
583 // Initialize the incoming context. 585 // Initialize the incoming context.
584 ContextScope incoming_context(this, scope(), false); 586 ContextScope incoming_context(this, scope(), false);
585 587
586 // Initialize control scope. 588 // Initialize control scope.
587 ControlScopeForTopLevel control(this); 589 ControlScopeForTopLevel control(this);
588 590
591 if (IsGeneratorFunction(info->literal()->kind())) {
592 VisitGeneratorPrologue();
593 }
594
589 // Build function context only if there are context allocated variables. 595 // Build function context only if there are context allocated variables.
590 if (scope()->NeedsContext()) { 596 if (scope()->NeedsContext()) {
591 // Push a new inner context scope for the function. 597 // Push a new inner context scope for the function.
592 VisitNewLocalFunctionContext(); 598 VisitNewLocalFunctionContext();
593 ContextScope local_function_context(this, scope(), false); 599 ContextScope local_function_context(this, scope(), false);
594 VisitBuildLocalActivationContext(); 600 VisitBuildLocalActivationContext();
595 MakeBytecodeBody(); 601 MakeBytecodeBody();
596 } else { 602 } else {
597 MakeBytecodeBody(); 603 MakeBytecodeBody();
598 } 604 }
(...skipping 28 matching lines...) Expand all
627 // Visit declarations within the function scope. 633 // Visit declarations within the function scope.
628 VisitDeclarations(scope()->declarations()); 634 VisitDeclarations(scope()->declarations());
629 635
630 // Perform a stack-check before the body. 636 // Perform a stack-check before the body.
631 builder()->StackCheck(); 637 builder()->StackCheck();
632 638
633 // Visit statements in the function body. 639 // Visit statements in the function body.
634 VisitStatements(info()->literal()->body()); 640 VisitStatements(info()->literal()->body());
635 } 641 }
636 642
643 void BytecodeGenerator::VisitGeneratorPrologue() {
644 generator_resume_points_.clear();
645 generator_resume_points_.resize(info()->literal()->yield_count());
646
647 BytecodeLabel regular_call;
648 builder()
649 ->LoadAccumulatorWithRegister(Register::new_target())
650 .JumpIfUndefined(&regular_call);
651
652 // This is a resume call. Restore registers and perform state dispatch.
653 // (The current context has already been restored by the trampoline.)
654 {
655 RegisterAllocationScope register_scope(this);
656 Register state = register_allocator()->NewRegister();
657 builder()
658 ->CallRuntime(Runtime::kResumeIgnitionGenerator, Register::new_target(),
659 1)
660 .StoreAccumulatorInRegister(state);
661
662 // TODO(neis): Optimize this by using a proper jump table.
663 for (size_t i = 0; i < generator_resume_points_.size(); ++i) {
664 builder()
665 ->LoadLiteral(Smi::FromInt(static_cast<int>(i)))
666 .CompareOperation(Token::Value::EQ_STRICT, state)
667 .JumpIfTrue(&(generator_resume_points_[i]));
668 }
669 builder()->Illegal(); // Should never get here.
670 }
671
672 builder()->Bind(&regular_call);
673 // This is a regular call. Fall through to the ordinary function prologue,
674 // after which we will run into the generator object creation and the initial
675 // yield (both inserted by the parser).
676 }
637 677
638 void BytecodeGenerator::VisitBlock(Block* stmt) { 678 void BytecodeGenerator::VisitBlock(Block* stmt) {
639 // Visit declarations and statements. 679 // Visit declarations and statements.
640 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { 680 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
641 VisitNewLocalBlockContext(stmt->scope()); 681 VisitNewLocalBlockContext(stmt->scope());
642 ContextScope scope(this, stmt->scope()); 682 ContextScope scope(this, stmt->scope());
643 VisitBlockDeclarationsAndStatements(stmt); 683 VisitBlockDeclarationsAndStatements(stmt);
644 } else { 684 } else {
645 VisitBlockDeclarationsAndStatements(stmt); 685 VisitBlockDeclarationsAndStatements(stmt);
646 } 686 }
(...skipping 1575 matching lines...) Expand 10 before | Expand all | Expand 10 after
2222 } 2262 }
2223 case KEYED_SUPER_PROPERTY: { 2263 case KEYED_SUPER_PROPERTY: {
2224 builder()->StoreAccumulatorInRegister(value); 2264 builder()->StoreAccumulatorInRegister(value);
2225 BuildKeyedSuperPropertyStore(object, home_object, key, value); 2265 BuildKeyedSuperPropertyStore(object, home_object, key, value);
2226 break; 2266 break;
2227 } 2267 }
2228 } 2268 }
2229 execution_result()->SetResultInAccumulator(); 2269 execution_result()->SetResultInAccumulator();
2230 } 2270 }
2231 2271
2272 void BytecodeGenerator::VisitYield(Yield* expr) {
2273 int id = generator_yields_seen_++;
2232 2274
2233 void BytecodeGenerator::VisitYield(Yield* expr) { UNIMPLEMENTED(); } 2275 builder()->SetExpressionPosition(expr);
2276 Register value = VisitForRegisterValue(expr->expression());
2234 2277
2278 register_allocator()->PrepareForConsecutiveAllocations(2);
2279 Register generator = register_allocator()->NextConsecutiveRegister();
2280 Register state = register_allocator()->NextConsecutiveRegister();
2281
2282 // Save context, registers, and state. Then return.
2283 VisitForRegisterValue(expr->generator_object(), generator);
2284 builder()
2285 ->LoadLiteral(Smi::FromInt(id))
2286 .StoreAccumulatorInRegister(state)
2287 .CallRuntime(Runtime::kSuspendIgnitionGenerator, generator, 2)
2288 .LoadAccumulatorWithRegister(value)
2289 .Return(); // Hard return (ignore any finally blocks).
2290
2291 builder()->Bind(&(generator_resume_points_[id]));
2292 // Upon resume, we continue here.
2293
2294 {
2295 RegisterAllocationScope register_scope(this);
2296
2297 Register input = register_allocator()->NewRegister();
2298 builder()
2299 ->CallRuntime(Runtime::kGeneratorGetInput, generator, 1)
2300 .StoreAccumulatorInRegister(input);
2301
2302 Register resume_mode = register_allocator()->NewRegister();
2303 builder()
2304 ->CallRuntime(Runtime::kGeneratorGetResumeMode, generator, 1)
2305 .StoreAccumulatorInRegister(resume_mode);
2306
2307 // Now dispatch on resume mode.
2308
2309 BytecodeLabel resume_with_next;
2310 BytecodeLabel resume_with_return;
2311 BytecodeLabel resume_with_throw;
2312
2313 builder()
2314 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
2315 .CompareOperation(Token::EQ_STRICT, resume_mode)
2316 .JumpIfTrue(&resume_with_next)
2317 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow))
2318 .CompareOperation(Token::EQ_STRICT, resume_mode)
2319 .JumpIfTrue(&resume_with_throw)
2320 .Jump(&resume_with_return);
Jarin 2016/04/18 13:55:06 Out of curiosity, do you even need the Jump?
neis 2016/04/18 14:07:52 Shhh :)
2321
2322 builder()->Bind(&resume_with_return);
2323 {
2324 register_allocator()->PrepareForConsecutiveAllocations(2);
2325 Register value = register_allocator()->NextConsecutiveRegister();
2326 Register done = register_allocator()->NextConsecutiveRegister();
2327 builder()
2328 ->MoveRegister(input, value)
2329 .LoadTrue()
2330 .StoreAccumulatorInRegister(done)
2331 .CallRuntime(Runtime::kCreateIterResultObject, value, 2);
2332 execution_control()->ReturnAccumulator();
2333 }
2334
2335 builder()->Bind(&resume_with_throw);
2336 builder()
2337 ->LoadAccumulatorWithRegister(input)
2338 .Throw();
2339
2340 builder()->Bind(&resume_with_next);
2341 builder()->LoadAccumulatorWithRegister(input);
2342 }
2343 execution_result()->SetResultInAccumulator();
2344 }
2235 2345
2236 void BytecodeGenerator::VisitThrow(Throw* expr) { 2346 void BytecodeGenerator::VisitThrow(Throw* expr) {
2237 VisitForAccumulatorValue(expr->exception()); 2347 VisitForAccumulatorValue(expr->exception());
2238 builder()->SetExpressionPosition(expr); 2348 builder()->SetExpressionPosition(expr);
2239 builder()->Throw(); 2349 builder()->Throw();
2240 // Throw statments are modeled as expression instead of statments. These are 2350 // Throw statements are modeled as expressions instead of statements. These
2241 // converted from assignment statements in Rewriter::ReWrite pass. An 2351 // are converted from assignment statements in Rewriter::ReWrite pass. An
2242 // assignment statement expects a value in the accumulator. This is a hack to 2352 // assignment statement expects a value in the accumulator. This is a hack to
2243 // avoid DCHECK fails assert accumulator has been set. 2353 // avoid DCHECK fails assert accumulator has been set.
2244 execution_result()->SetResultInAccumulator(); 2354 execution_result()->SetResultInAccumulator();
2245 } 2355 }
2246 2356
2247 2357
2248 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { 2358 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
2249 LhsKind property_kind = Property::GetAssignType(expr); 2359 LhsKind property_kind = Property::GetAssignType(expr);
2250 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); 2360 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
2251 builder()->SetExpressionPosition(expr); 2361 builder()->SetExpressionPosition(expr);
(...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after
3160 } 3270 }
3161 3271
3162 3272
3163 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 3273 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
3164 return info()->shared_info()->feedback_vector()->GetIndex(slot); 3274 return info()->shared_info()->feedback_vector()->GetIndex(slot);
3165 } 3275 }
3166 3276
3167 } // namespace interpreter 3277 } // namespace interpreter
3168 } // namespace internal 3278 } // namespace internal
3169 } // namespace v8 3279 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecode-register-allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698