| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 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/v8.h" | 
|  | 6 | 
|  | 7 #include "src/arguments.h" | 
|  | 8 #include "src/frames-inl.h" | 
|  | 9 #include "src/runtime/runtime.h" | 
|  | 10 #include "src/runtime/runtime-utils.h" | 
|  | 11 | 
|  | 12 namespace v8 { | 
|  | 13 namespace internal { | 
|  | 14 | 
|  | 15 RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) { | 
|  | 16   HandleScope scope(isolate); | 
|  | 17   DCHECK(args.length() == 0); | 
|  | 18 | 
|  | 19   JavaScriptFrameIterator it(isolate); | 
|  | 20   JavaScriptFrame* frame = it.frame(); | 
|  | 21   Handle<JSFunction> function(frame->function()); | 
|  | 22   RUNTIME_ASSERT(function->shared()->is_generator()); | 
|  | 23 | 
|  | 24   Handle<JSGeneratorObject> generator; | 
|  | 25   if (frame->IsConstructor()) { | 
|  | 26     generator = handle(JSGeneratorObject::cast(frame->receiver())); | 
|  | 27   } else { | 
|  | 28     generator = isolate->factory()->NewJSGeneratorObject(function); | 
|  | 29   } | 
|  | 30   generator->set_function(*function); | 
|  | 31   generator->set_context(Context::cast(frame->context())); | 
|  | 32   generator->set_receiver(frame->receiver()); | 
|  | 33   generator->set_continuation(0); | 
|  | 34   generator->set_operand_stack(isolate->heap()->empty_fixed_array()); | 
|  | 35   generator->set_stack_handler_index(-1); | 
|  | 36 | 
|  | 37   return *generator; | 
|  | 38 } | 
|  | 39 | 
|  | 40 | 
|  | 41 RUNTIME_FUNCTION(Runtime_SuspendJSGeneratorObject) { | 
|  | 42   HandleScope handle_scope(isolate); | 
|  | 43   DCHECK(args.length() == 1); | 
|  | 44   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0); | 
|  | 45 | 
|  | 46   JavaScriptFrameIterator stack_iterator(isolate); | 
|  | 47   JavaScriptFrame* frame = stack_iterator.frame(); | 
|  | 48   RUNTIME_ASSERT(frame->function()->shared()->is_generator()); | 
|  | 49   DCHECK_EQ(frame->function(), generator_object->function()); | 
|  | 50 | 
|  | 51   // The caller should have saved the context and continuation already. | 
|  | 52   DCHECK_EQ(generator_object->context(), Context::cast(frame->context())); | 
|  | 53   DCHECK_LT(0, generator_object->continuation()); | 
|  | 54 | 
|  | 55   // We expect there to be at least two values on the operand stack: the return | 
|  | 56   // value of the yield expression, and the argument to this runtime call. | 
|  | 57   // Neither of those should be saved. | 
|  | 58   int operands_count = frame->ComputeOperandsCount(); | 
|  | 59   DCHECK_GE(operands_count, 2); | 
|  | 60   operands_count -= 2; | 
|  | 61 | 
|  | 62   if (operands_count == 0) { | 
|  | 63     // Although it's semantically harmless to call this function with an | 
|  | 64     // operands_count of zero, it is also unnecessary. | 
|  | 65     DCHECK_EQ(generator_object->operand_stack(), | 
|  | 66               isolate->heap()->empty_fixed_array()); | 
|  | 67     DCHECK_EQ(generator_object->stack_handler_index(), -1); | 
|  | 68     // If there are no operands on the stack, there shouldn't be a handler | 
|  | 69     // active either. | 
|  | 70     DCHECK(!frame->HasHandler()); | 
|  | 71   } else { | 
|  | 72     int stack_handler_index = -1; | 
|  | 73     Handle<FixedArray> operand_stack = | 
|  | 74         isolate->factory()->NewFixedArray(operands_count); | 
|  | 75     frame->SaveOperandStack(*operand_stack, &stack_handler_index); | 
|  | 76     generator_object->set_operand_stack(*operand_stack); | 
|  | 77     generator_object->set_stack_handler_index(stack_handler_index); | 
|  | 78   } | 
|  | 79 | 
|  | 80   return isolate->heap()->undefined_value(); | 
|  | 81 } | 
|  | 82 | 
|  | 83 | 
|  | 84 // Note that this function is the slow path for resuming generators.  It is only | 
|  | 85 // called if the suspended activation had operands on the stack, stack handlers | 
|  | 86 // needing rewinding, or if the resume should throw an exception.  The fast path | 
|  | 87 // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is | 
|  | 88 // inlined into GeneratorNext and GeneratorThrow.  EmitGeneratorResumeResume is | 
|  | 89 // called in any case, as it needs to reconstruct the stack frame and make space | 
|  | 90 // for arguments and operands. | 
|  | 91 RUNTIME_FUNCTION(Runtime_ResumeJSGeneratorObject) { | 
|  | 92   SealHandleScope shs(isolate); | 
|  | 93   DCHECK(args.length() == 3); | 
|  | 94   CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0); | 
|  | 95   CONVERT_ARG_CHECKED(Object, value, 1); | 
|  | 96   CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2); | 
|  | 97   JavaScriptFrameIterator stack_iterator(isolate); | 
|  | 98   JavaScriptFrame* frame = stack_iterator.frame(); | 
|  | 99 | 
|  | 100   DCHECK_EQ(frame->function(), generator_object->function()); | 
|  | 101   DCHECK(frame->function()->is_compiled()); | 
|  | 102 | 
|  | 103   STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); | 
|  | 104   STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); | 
|  | 105 | 
|  | 106   Address pc = generator_object->function()->code()->instruction_start(); | 
|  | 107   int offset = generator_object->continuation(); | 
|  | 108   DCHECK(offset > 0); | 
|  | 109   frame->set_pc(pc + offset); | 
|  | 110   if (FLAG_enable_ool_constant_pool) { | 
|  | 111     frame->set_constant_pool( | 
|  | 112         generator_object->function()->code()->constant_pool()); | 
|  | 113   } | 
|  | 114   generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting); | 
|  | 115 | 
|  | 116   FixedArray* operand_stack = generator_object->operand_stack(); | 
|  | 117   int operands_count = operand_stack->length(); | 
|  | 118   if (operands_count != 0) { | 
|  | 119     frame->RestoreOperandStack(operand_stack, | 
|  | 120                                generator_object->stack_handler_index()); | 
|  | 121     generator_object->set_operand_stack(isolate->heap()->empty_fixed_array()); | 
|  | 122     generator_object->set_stack_handler_index(-1); | 
|  | 123   } | 
|  | 124 | 
|  | 125   JSGeneratorObject::ResumeMode resume_mode = | 
|  | 126       static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int); | 
|  | 127   switch (resume_mode) { | 
|  | 128     case JSGeneratorObject::NEXT: | 
|  | 129       return value; | 
|  | 130     case JSGeneratorObject::THROW: | 
|  | 131       return isolate->Throw(value); | 
|  | 132   } | 
|  | 133 | 
|  | 134   UNREACHABLE(); | 
|  | 135   return isolate->ThrowIllegalOperation(); | 
|  | 136 } | 
|  | 137 | 
|  | 138 | 
|  | 139 RUNTIME_FUNCTION(Runtime_ThrowGeneratorStateError) { | 
|  | 140   HandleScope scope(isolate); | 
|  | 141   DCHECK(args.length() == 1); | 
|  | 142   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | 
|  | 143   int continuation = generator->continuation(); | 
|  | 144   const char* message = continuation == JSGeneratorObject::kGeneratorClosed | 
|  | 145                             ? "generator_finished" | 
|  | 146                             : "generator_running"; | 
|  | 147   Vector<Handle<Object> > argv = HandleVector<Object>(NULL, 0); | 
|  | 148   THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewError(message, argv)); | 
|  | 149 } | 
|  | 150 | 
|  | 151 | 
|  | 152 // Returns function of generator activation. | 
|  | 153 RUNTIME_FUNCTION(Runtime_GeneratorGetFunction) { | 
|  | 154   HandleScope scope(isolate); | 
|  | 155   DCHECK(args.length() == 1); | 
|  | 156   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | 
|  | 157 | 
|  | 158   return generator->function(); | 
|  | 159 } | 
|  | 160 | 
|  | 161 | 
|  | 162 // Returns context of generator activation. | 
|  | 163 RUNTIME_FUNCTION(Runtime_GeneratorGetContext) { | 
|  | 164   HandleScope scope(isolate); | 
|  | 165   DCHECK(args.length() == 1); | 
|  | 166   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | 
|  | 167 | 
|  | 168   return generator->context(); | 
|  | 169 } | 
|  | 170 | 
|  | 171 | 
|  | 172 // Returns receiver of generator activation. | 
|  | 173 RUNTIME_FUNCTION(Runtime_GeneratorGetReceiver) { | 
|  | 174   HandleScope scope(isolate); | 
|  | 175   DCHECK(args.length() == 1); | 
|  | 176   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | 
|  | 177 | 
|  | 178   return generator->receiver(); | 
|  | 179 } | 
|  | 180 | 
|  | 181 | 
|  | 182 // Returns generator continuation as a PC offset, or the magic -1 or 0 values. | 
|  | 183 RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) { | 
|  | 184   HandleScope scope(isolate); | 
|  | 185   DCHECK(args.length() == 1); | 
|  | 186   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | 
|  | 187 | 
|  | 188   return Smi::FromInt(generator->continuation()); | 
|  | 189 } | 
|  | 190 | 
|  | 191 | 
|  | 192 RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) { | 
|  | 193   HandleScope scope(isolate); | 
|  | 194   DCHECK(args.length() == 1); | 
|  | 195   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | 
|  | 196 | 
|  | 197   if (generator->is_suspended()) { | 
|  | 198     Handle<Code> code(generator->function()->code(), isolate); | 
|  | 199     int offset = generator->continuation(); | 
|  | 200 | 
|  | 201     RUNTIME_ASSERT(0 <= offset && offset < code->Size()); | 
|  | 202     Address pc = code->address() + offset; | 
|  | 203 | 
|  | 204     return Smi::FromInt(code->SourcePosition(pc)); | 
|  | 205   } | 
|  | 206 | 
|  | 207   return isolate->heap()->undefined_value(); | 
|  | 208 } | 
|  | 209 | 
|  | 210 | 
|  | 211 RUNTIME_FUNCTION(Runtime_FunctionIsGenerator) { | 
|  | 212   SealHandleScope shs(isolate); | 
|  | 213   DCHECK(args.length() == 1); | 
|  | 214   CONVERT_ARG_CHECKED(JSFunction, f, 0); | 
|  | 215   return isolate->heap()->ToBoolean(f->shared()->is_generator()); | 
|  | 216 } | 
|  | 217 | 
|  | 218 | 
|  | 219 RUNTIME_FUNCTION(RuntimeReference_GeneratorNext) { | 
|  | 220   UNREACHABLE();  // Optimization disabled in SetUpGenerators(). | 
|  | 221   return NULL; | 
|  | 222 } | 
|  | 223 | 
|  | 224 | 
|  | 225 RUNTIME_FUNCTION(RuntimeReference_GeneratorThrow) { | 
|  | 226   UNREACHABLE();  // Optimization disabled in SetUpGenerators(). | 
|  | 227   return NULL; | 
|  | 228 } | 
|  | 229 } | 
|  | 230 }  // namespace v8::internal | 
| OLD | NEW | 
|---|