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

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

Powered by Google App Engine
This is Rietveld 408576698