Home | History | Annotate | Download | only in runtime
      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
      3 // found in the LICENSE file.
      4 
      5 #include "src/runtime/runtime-utils.h"
      6 
      7 #include "src/arguments.h"
      8 #include "src/debug/debug.h"
      9 #include "src/factory.h"
     10 #include "src/frames-inl.h"
     11 #include "src/objects-inl.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) {
     17   HandleScope scope(isolate);
     18   DCHECK(args.length() == 2);
     19   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
     20   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
     21   CHECK(function->shared()->is_resumable());
     22 
     23   Handle<FixedArray> operand_stack;
     24   if (function->shared()->HasBytecodeArray()) {
     25     // New-style generators.
     26     int size = function->shared()->bytecode_array()->register_count();
     27     operand_stack = isolate->factory()->NewFixedArray(size);
     28   } else {
     29     // Old-style generators.
     30     operand_stack = handle(isolate->heap()->empty_fixed_array());
     31   }
     32 
     33   Handle<JSGeneratorObject> generator =
     34       isolate->factory()->NewJSGeneratorObject(function);
     35   generator->set_function(*function);
     36   generator->set_context(isolate->context());
     37   generator->set_receiver(*receiver);
     38   generator->set_operand_stack(*operand_stack);
     39   generator->set_continuation(JSGeneratorObject::kGeneratorExecuting);
     40   return *generator;
     41 }
     42 
     43 RUNTIME_FUNCTION(Runtime_SuspendJSGeneratorObject) {
     44   HandleScope handle_scope(isolate);
     45   DCHECK(args.length() == 1);
     46   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0);
     47 
     48   JavaScriptFrameIterator stack_iterator(isolate);
     49   JavaScriptFrame* frame = stack_iterator.frame();
     50   CHECK(frame->function()->shared()->is_resumable());
     51   DCHECK_EQ(frame->function(), generator_object->function());
     52   DCHECK(frame->function()->shared()->is_compiled());
     53   DCHECK(!frame->function()->IsOptimized());
     54 
     55   isolate->debug()->RecordAsyncFunction(generator_object);
     56 
     57   // The caller should have saved the context and continuation already.
     58   DCHECK_EQ(generator_object->context(), Context::cast(frame->context()));
     59   DCHECK_LT(0, generator_object->continuation());
     60 
     61   // We expect there to be at least two values on the operand stack: the return
     62   // value of the yield expression, and the arguments to this runtime call.
     63   // Neither of those should be saved.
     64   int operands_count = frame->ComputeOperandsCount();
     65   DCHECK_GE(operands_count, 1 + args.length());
     66   operands_count -= 1 + args.length();
     67 
     68   if (operands_count == 0) {
     69     // Although it's semantically harmless to call this function with an
     70     // operands_count of zero, it is also unnecessary.
     71     DCHECK_EQ(generator_object->operand_stack(),
     72               isolate->heap()->empty_fixed_array());
     73   } else {
     74     Handle<FixedArray> operand_stack =
     75         isolate->factory()->NewFixedArray(operands_count);
     76     frame->SaveOperandStack(*operand_stack);
     77     generator_object->set_operand_stack(*operand_stack);
     78   }
     79 
     80   return isolate->heap()->undefined_value();
     81 }
     82 
     83 RUNTIME_FUNCTION(Runtime_GeneratorClose) {
     84   HandleScope scope(isolate);
     85   DCHECK(args.length() == 1);
     86   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
     87 
     88   generator->set_continuation(JSGeneratorObject::kGeneratorClosed);
     89 
     90   return isolate->heap()->undefined_value();
     91 }
     92 
     93 RUNTIME_FUNCTION(Runtime_GeneratorGetFunction) {
     94   HandleScope scope(isolate);
     95   DCHECK(args.length() == 1);
     96   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
     97 
     98   return generator->function();
     99 }
    100 
    101 RUNTIME_FUNCTION(Runtime_GeneratorGetReceiver) {
    102   HandleScope scope(isolate);
    103   DCHECK(args.length() == 1);
    104   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
    105 
    106   return generator->receiver();
    107 }
    108 
    109 RUNTIME_FUNCTION(Runtime_GeneratorGetInputOrDebugPos) {
    110   HandleScope scope(isolate);
    111   DCHECK(args.length() == 1);
    112   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
    113 
    114   return generator->input_or_debug_pos();
    115 }
    116 
    117 RUNTIME_FUNCTION(Runtime_GeneratorGetResumeMode) {
    118   HandleScope scope(isolate);
    119   DCHECK(args.length() == 1);
    120   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
    121 
    122   return Smi::FromInt(generator->resume_mode());
    123 }
    124 
    125 RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) {
    126   HandleScope scope(isolate);
    127   DCHECK(args.length() == 1);
    128   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
    129 
    130   return Smi::FromInt(generator->continuation());
    131 }
    132 
    133 RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) {
    134   HandleScope scope(isolate);
    135   DCHECK(args.length() == 1);
    136   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
    137 
    138   if (!generator->is_suspended()) return isolate->heap()->undefined_value();
    139   return Smi::FromInt(generator->source_position());
    140 }
    141 
    142 }  // namespace internal
    143 }  // namespace v8
    144