OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1994 // this. It stays on the stack while we update the iterator. | 1994 // this. It stays on the stack while we update the iterator. |
1995 VisitForStackValue(expr->expression()); | 1995 VisitForStackValue(expr->expression()); |
1996 | 1996 |
1997 switch (expr->yield_kind()) { | 1997 switch (expr->yield_kind()) { |
1998 case Yield::SUSPEND: | 1998 case Yield::SUSPEND: |
1999 // Pop value from top-of-stack slot; box result into result register. | 1999 // Pop value from top-of-stack slot; box result into result register. |
2000 EmitCreateIteratorResult(false); | 2000 EmitCreateIteratorResult(false); |
2001 __ push(result_register()); | 2001 __ push(result_register()); |
2002 // Fall through. | 2002 // Fall through. |
2003 case Yield::INITIAL: { | 2003 case Yield::INITIAL: { |
2004 VisitForStackValue(expr->generator_object()); | 2004 Label suspend, continuation, post_runtime, resume; |
| 2005 |
| 2006 __ jmp(&suspend); |
| 2007 |
| 2008 __ bind(&continuation); |
| 2009 __ jmp(&resume); |
| 2010 |
| 2011 __ bind(&suspend); |
| 2012 VisitForAccumulatorValue(expr->generator_object()); |
| 2013 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
| 2014 __ li(a1, Operand(Smi::FromInt(continuation.pos()))); |
| 2015 __ sw(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset)); |
| 2016 __ sw(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset)); |
| 2017 __ mov(a1, cp); |
| 2018 __ RecordWriteField(v0, JSGeneratorObject::kContextOffset, a1, a2, |
| 2019 kRAHasBeenSaved, kDontSaveFPRegs); |
| 2020 __ Addu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); |
| 2021 __ Branch(&post_runtime, eq, sp, Operand(a1)); |
| 2022 __ push(v0); // generator object |
2005 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2023 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
2006 __ lw(context_register(), | 2024 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2007 MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2025 __ bind(&post_runtime); |
2008 | |
2009 Label resume; | |
2010 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | |
2011 __ Branch(&resume, ne, result_register(), Operand(at)); | |
2012 __ pop(result_register()); | 2026 __ pop(result_register()); |
2013 EmitReturnSequence(); | 2027 EmitReturnSequence(); |
2014 | 2028 |
2015 __ bind(&resume); | 2029 __ bind(&resume); |
2016 context()->Plug(result_register()); | 2030 context()->Plug(result_register()); |
2017 break; | 2031 break; |
2018 } | 2032 } |
2019 | 2033 |
2020 case Yield::FINAL: { | 2034 case Yield::FINAL: { |
2021 VisitForAccumulatorValue(expr->generator_object()); | 2035 VisitForAccumulatorValue(expr->generator_object()); |
2022 __ li(a1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); | 2036 __ li(a1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); |
2023 __ sw(a1, FieldMemOperand(result_register(), | 2037 __ sw(a1, FieldMemOperand(result_register(), |
2024 JSGeneratorObject::kContinuationOffset)); | 2038 JSGeneratorObject::kContinuationOffset)); |
2025 // Pop value from top-of-stack slot, box result into result register. | 2039 // Pop value from top-of-stack slot, box result into result register. |
2026 EmitCreateIteratorResult(true); | 2040 EmitCreateIteratorResult(true); |
2027 EmitUnwindBeforeReturn(); | 2041 EmitUnwindBeforeReturn(); |
2028 EmitReturnSequence(); | 2042 EmitReturnSequence(); |
2029 break; | 2043 break; |
2030 } | 2044 } |
2031 | 2045 |
2032 case Yield::DELEGATING: { | 2046 case Yield::DELEGATING: { |
2033 VisitForStackValue(expr->generator_object()); | 2047 VisitForStackValue(expr->generator_object()); |
2034 | 2048 |
2035 // Initial stack layout is as follows: | 2049 // Initial stack layout is as follows: |
2036 // [sp + 1 * kPointerSize] iter | 2050 // [sp + 1 * kPointerSize] iter |
2037 // [sp + 0 * kPointerSize] g | 2051 // [sp + 0 * kPointerSize] g |
2038 | 2052 |
2039 Label l_catch, l_try, l_resume, l_next, l_call, l_loop; | 2053 Label l_catch, l_try, l_suspend, l_continuation, l_resume; |
| 2054 Label l_next, l_call, l_loop; |
2040 // Initial send value is undefined. | 2055 // Initial send value is undefined. |
2041 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 2056 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
2042 __ Branch(&l_next); | 2057 __ Branch(&l_next); |
2043 | 2058 |
2044 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 2059 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
2045 __ bind(&l_catch); | 2060 __ bind(&l_catch); |
2046 __ mov(a0, v0); | 2061 __ mov(a0, v0); |
2047 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 2062 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
2048 __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw" | 2063 __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw" |
2049 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter | 2064 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter |
2050 __ push(a3); // iter | 2065 __ push(a3); // iter |
2051 __ push(a0); // exception | 2066 __ push(a0); // exception |
2052 __ jmp(&l_call); | 2067 __ jmp(&l_call); |
2053 | 2068 |
2054 // try { received = %yield result } | 2069 // try { received = %yield result } |
2055 // Shuffle the received result above a try handler and yield it without | 2070 // Shuffle the received result above a try handler and yield it without |
2056 // re-boxing. | 2071 // re-boxing. |
2057 __ bind(&l_try); | 2072 __ bind(&l_try); |
2058 __ pop(a0); // result | 2073 __ pop(a0); // result |
2059 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2074 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
2060 const int handler_size = StackHandlerConstants::kSize; | 2075 const int handler_size = StackHandlerConstants::kSize; |
2061 __ push(a0); // result | 2076 __ push(a0); // result |
2062 __ lw(a3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size)); // g | 2077 __ jmp(&l_suspend); |
2063 __ push(a3); // g | 2078 __ bind(&l_continuation); |
| 2079 __ mov(a0, v0); |
| 2080 __ jmp(&l_resume); |
| 2081 __ bind(&l_suspend); |
| 2082 const int generator_object_depth = kPointerSize + handler_size; |
| 2083 __ lw(a0, MemOperand(sp, generator_object_depth)); |
| 2084 __ push(a0); // g |
| 2085 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
| 2086 __ li(a1, Operand(Smi::FromInt(l_continuation.pos()))); |
| 2087 __ sw(a1, FieldMemOperand(a0, JSGeneratorObject::kContinuationOffset)); |
| 2088 __ sw(cp, FieldMemOperand(a0, JSGeneratorObject::kContextOffset)); |
| 2089 __ mov(a1, cp); |
| 2090 __ RecordWriteField(a0, JSGeneratorObject::kContextOffset, a1, a2, |
| 2091 kRAHasBeenSaved, kDontSaveFPRegs); |
2064 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2092 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
2065 __ mov(a0, v0); | 2093 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2066 __ lw(context_register(), | |
2067 MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
2068 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | |
2069 __ Branch(&l_resume, ne, a0, Operand(at)); | |
2070 __ pop(v0); // result | 2094 __ pop(v0); // result |
2071 EmitReturnSequence(); | 2095 EmitReturnSequence(); |
2072 __ mov(a0, v0); | 2096 __ mov(a0, v0); |
2073 __ bind(&l_resume); // received in a0 | 2097 __ bind(&l_resume); // received in a0 |
2074 __ PopTryHandler(); | 2098 __ PopTryHandler(); |
2075 | 2099 |
2076 // receiver = iter; f = 'next'; arg = received; | 2100 // receiver = iter; f = 'next'; arg = received; |
2077 __ bind(&l_next); | 2101 __ bind(&l_next); |
2078 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" | 2102 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" |
2079 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter | 2103 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter |
(...skipping 2847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4927 *context_length = 0; | 4951 *context_length = 0; |
4928 return previous_; | 4952 return previous_; |
4929 } | 4953 } |
4930 | 4954 |
4931 | 4955 |
4932 #undef __ | 4956 #undef __ |
4933 | 4957 |
4934 } } // namespace v8::internal | 4958 } } // namespace v8::internal |
4935 | 4959 |
4936 #endif // V8_TARGET_ARCH_MIPS | 4960 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |