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

Side by Side Diff: src/x64/full-codegen-x64.cc

Issue 16801006: Allocate generator result objects before unwinding try handlers (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Switch fallthrough for yield boxing Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | test/mjsunit/mjsunit.status » ('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 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 1956 matching lines...) Expand 10 before | Expand all | Expand 10 after
1967 } 1967 }
1968 1968
1969 1969
1970 void FullCodeGenerator::VisitYield(Yield* expr) { 1970 void FullCodeGenerator::VisitYield(Yield* expr) {
1971 Comment cmnt(masm_, "[ Yield"); 1971 Comment cmnt(masm_, "[ Yield");
1972 // Evaluate yielded value first; the initial iterator definition depends on 1972 // Evaluate yielded value first; the initial iterator definition depends on
1973 // this. It stays on the stack while we update the iterator. 1973 // this. It stays on the stack while we update the iterator.
1974 VisitForStackValue(expr->expression()); 1974 VisitForStackValue(expr->expression());
1975 1975
1976 switch (expr->yield_kind()) { 1976 switch (expr->yield_kind()) {
1977 case Yield::INITIAL: 1977 case Yield::SUSPEND:
1978 case Yield::SUSPEND: { 1978 // Pop value from top-of-stack slot; box result into result register.
1979 EmitCreateIteratorResult(false);
1980 __ push(result_register());
1981 // Fall through.
1982 case Yield::INITIAL: {
1979 VisitForStackValue(expr->generator_object()); 1983 VisitForStackValue(expr->generator_object());
1980 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 1984 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1981 __ movq(context_register(), 1985 __ movq(context_register(),
1982 Operand(rbp, StandardFrameConstants::kContextOffset)); 1986 Operand(rbp, StandardFrameConstants::kContextOffset));
1983 1987
1984 Label resume; 1988 Label resume;
1985 __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex); 1989 __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex);
1986 __ j(not_equal, &resume); 1990 __ j(not_equal, &resume);
1987 if (expr->yield_kind() == Yield::SUSPEND) { 1991 __ pop(result_register());
1988 EmitReturnIteratorResult(false); 1992 EmitReturnSequence();
1989 } else {
1990 __ pop(result_register());
1991 EmitReturnSequence();
1992 }
1993 1993
1994 __ bind(&resume); 1994 __ bind(&resume);
1995 context()->Plug(result_register()); 1995 context()->Plug(result_register());
1996 break; 1996 break;
1997 } 1997 }
1998 1998
1999 case Yield::FINAL: { 1999 case Yield::FINAL: {
2000 VisitForAccumulatorValue(expr->generator_object()); 2000 VisitForAccumulatorValue(expr->generator_object());
2001 __ Move(FieldOperand(result_register(), 2001 __ Move(FieldOperand(result_register(),
2002 JSGeneratorObject::kContinuationOffset), 2002 JSGeneratorObject::kContinuationOffset),
2003 Smi::FromInt(JSGeneratorObject::kGeneratorClosed)); 2003 Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
2004 EmitReturnIteratorResult(true); 2004 // Pop value from top-of-stack slot, box result into result register.
2005 EmitCreateIteratorResult(true);
2006 EmitUnwindBeforeReturn();
2007 EmitReturnSequence();
2005 break; 2008 break;
2006 } 2009 }
2007 2010
2008 case Yield::DELEGATING: { 2011 case Yield::DELEGATING: {
2009 VisitForStackValue(expr->generator_object()); 2012 VisitForStackValue(expr->generator_object());
2010 2013
2011 // Initial stack layout is as follows: 2014 // Initial stack layout is as follows:
2012 // [sp + 1 * kPointerSize] iter 2015 // [sp + 1 * kPointerSize] iter
2013 // [sp + 0 * kPointerSize] g 2016 // [sp + 0 * kPointerSize] g
2014 2017
2015 Label l_catch, l_try, l_resume, l_next, l_call, l_loop; 2018 Label l_catch, l_try, l_resume, l_next, l_call, l_loop;
2016 // Initial send value is undefined. 2019 // Initial send value is undefined.
2017 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 2020 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2018 __ jmp(&l_next); 2021 __ jmp(&l_next);
2019 2022
2020 // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; } 2023 // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; }
2021 __ bind(&l_catch); 2024 __ bind(&l_catch);
2022 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 2025 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
2023 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); // iter 2026 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); // iter
2024 __ push(rcx); // iter 2027 __ push(rcx); // iter
2025 __ push(rax); // exception 2028 __ push(rax); // exception
2026 __ movq(rax, rcx); // iter 2029 __ movq(rax, rcx); // iter
2027 __ LoadRoot(rcx, Heap::kthrow_stringRootIndex); // "throw" 2030 __ LoadRoot(rcx, Heap::kthrow_stringRootIndex); // "throw"
2028 Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize(); 2031 Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize();
2029 CallIC(throw_ic); // iter.throw in rax 2032 CallIC(throw_ic); // iter.throw in rax
2030 __ jmp(&l_call); 2033 __ jmp(&l_call);
2031 2034
2032 // try { received = yield result.value } 2035 // try { received = yield result.value }
2033 __ bind(&l_try); 2036 __ bind(&l_try);
2034 __ pop(rax); // result.value 2037 EmitCreateIteratorResult(false); // pop and box to rax
2035 __ PushTryHandler(StackHandler::CATCH, expr->index()); 2038 __ PushTryHandler(StackHandler::CATCH, expr->index());
2036 const int handler_size = StackHandlerConstants::kSize; 2039 const int handler_size = StackHandlerConstants::kSize;
2037 __ push(rax); // result.value 2040 __ push(rax); // result
2038 __ push(Operand(rsp, (0 + 1) * kPointerSize + handler_size)); // g 2041 __ push(Operand(rsp, (0 + 1) * kPointerSize + handler_size)); // g
2039 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2042 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2040 __ movq(context_register(), 2043 __ movq(context_register(),
2041 Operand(rbp, StandardFrameConstants::kContextOffset)); 2044 Operand(rbp, StandardFrameConstants::kContextOffset));
2042 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 2045 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
2043 __ j(not_equal, &l_resume); 2046 __ j(not_equal, &l_resume);
2044 EmitReturnIteratorResult(false); 2047 __ pop(rax); // result
2048 EmitReturnSequence();
2045 __ bind(&l_resume); // received in rax 2049 __ bind(&l_resume); // received in rax
2046 __ PopTryHandler(); 2050 __ PopTryHandler();
2047 2051
2048 // receiver = iter; f = iter.next; arg = received; 2052 // receiver = iter; f = iter.next; arg = received;
2049 __ bind(&l_next); 2053 __ bind(&l_next);
2050 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); // iter 2054 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); // iter
2051 __ push(rcx); // iter 2055 __ push(rcx); // iter
2052 __ push(rax); // received 2056 __ push(rax); // received
2053 __ movq(rax, rcx); // iter 2057 __ movq(rax, rcx); // iter
2054 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next" 2058 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next"
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
2188 // Throw error if we attempt to operate on a running generator. 2192 // Throw error if we attempt to operate on a running generator.
2189 __ bind(&wrong_state); 2193 __ bind(&wrong_state);
2190 __ push(rbx); 2194 __ push(rbx);
2191 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); 2195 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
2192 2196
2193 __ bind(&done); 2197 __ bind(&done);
2194 context()->Plug(result_register()); 2198 context()->Plug(result_register());
2195 } 2199 }
2196 2200
2197 2201
2198 void FullCodeGenerator::EmitReturnIteratorResult(bool done) { 2202 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
2199 Label gc_required; 2203 Label gc_required;
2200 Label allocated; 2204 Label allocated;
2201 2205
2202 Handle<Map> map(isolate()->native_context()->generator_result_map()); 2206 Handle<Map> map(isolate()->native_context()->generator_result_map());
2203 2207
2204 __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT); 2208 __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT);
2209 __ jmp(&allocated);
2210
2211 __ bind(&gc_required);
2212 __ Push(Smi::FromInt(map->instance_size()));
2213 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2214 __ movq(context_register(),
2215 Operand(rbp, StandardFrameConstants::kContextOffset));
2205 2216
2206 __ bind(&allocated); 2217 __ bind(&allocated);
2207 __ Move(rbx, map); 2218 __ Move(rbx, map);
2208 __ pop(rcx); 2219 __ pop(rcx);
2209 __ Move(rdx, isolate()->factory()->ToBoolean(done)); 2220 __ Move(rdx, isolate()->factory()->ToBoolean(done));
2210 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); 2221 ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
2211 __ movq(FieldOperand(rax, HeapObject::kMapOffset), rbx); 2222 __ movq(FieldOperand(rax, HeapObject::kMapOffset), rbx);
2212 __ Move(FieldOperand(rax, JSObject::kPropertiesOffset), 2223 __ Move(FieldOperand(rax, JSObject::kPropertiesOffset),
2213 isolate()->factory()->empty_fixed_array()); 2224 isolate()->factory()->empty_fixed_array());
2214 __ Move(FieldOperand(rax, JSObject::kElementsOffset), 2225 __ Move(FieldOperand(rax, JSObject::kElementsOffset),
2215 isolate()->factory()->empty_fixed_array()); 2226 isolate()->factory()->empty_fixed_array());
2216 __ movq(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset), 2227 __ movq(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset),
2217 rcx); 2228 rcx);
2218 __ movq(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset), 2229 __ movq(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset),
2219 rdx); 2230 rdx);
2220 2231
2221 // Only the value field needs a write barrier, as the other values are in the 2232 // Only the value field needs a write barrier, as the other values are in the
2222 // root set. 2233 // root set.
2223 __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset, 2234 __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset,
2224 rcx, rdx, kDontSaveFPRegs); 2235 rcx, rdx, kDontSaveFPRegs);
2225
2226 if (done) {
2227 // Exit all nested statements.
2228 NestedStatement* current = nesting_stack_;
2229 int stack_depth = 0;
2230 int context_length = 0;
2231 while (current != NULL) {
2232 current = current->Exit(&stack_depth, &context_length);
2233 }
2234 __ Drop(stack_depth);
2235 }
2236
2237 EmitReturnSequence();
2238
2239 __ bind(&gc_required);
2240 __ Push(Smi::FromInt(map->instance_size()));
2241 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2242 __ movq(context_register(),
2243 Operand(rbp, StandardFrameConstants::kContextOffset));
2244 __ jmp(&allocated);
2245 } 2236 }
2246 2237
2247 2238
2248 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 2239 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2249 SetSourcePosition(prop->position()); 2240 SetSourcePosition(prop->position());
2250 Literal* key = prop->key()->AsLiteral(); 2241 Literal* key = prop->key()->AsLiteral();
2251 __ Move(rcx, key->handle()); 2242 __ Move(rcx, key->handle());
2252 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2243 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2253 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); 2244 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
2254 } 2245 }
(...skipping 2657 matching lines...) Expand 10 before | Expand all | Expand 10 after
4912 *context_length = 0; 4903 *context_length = 0;
4913 return previous_; 4904 return previous_;
4914 } 4905 }
4915 4906
4916 4907
4917 #undef __ 4908 #undef __
4918 4909
4919 } } // namespace v8::internal 4910 } } // namespace v8::internal
4920 4911
4921 #endif // V8_TARGET_ARCH_X64 4912 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | test/mjsunit/mjsunit.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698