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

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

Issue 141363005: A64: Synchronize with r15204. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 11 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/x64/code-stubs-x64.cc ('k') | src/x64/ic-x64.cc » ('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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 // o rsi: our context 111 // o rsi: our context
112 // o rbp: our caller's frame pointer 112 // o rbp: our caller's frame pointer
113 // o rsp: stack pointer (pointing to return address) 113 // o rsp: stack pointer (pointing to return address)
114 // 114 //
115 // The function builds a JS frame. Please see JavaScriptFrameConstants in 115 // The function builds a JS frame. Please see JavaScriptFrameConstants in
116 // frames-x64.h for its layout. 116 // frames-x64.h for its layout.
117 void FullCodeGenerator::Generate() { 117 void FullCodeGenerator::Generate() {
118 CompilationInfo* info = info_; 118 CompilationInfo* info = info_;
119 handler_table_ = 119 handler_table_ =
120 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 120 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
121 profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell( 121 profiling_counter_ = isolate()->factory()->NewCell(
122 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 122 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
123 SetFunctionPosition(function()); 123 SetFunctionPosition(function());
124 Comment cmnt(masm_, "[ function compiled by full code generator"); 124 Comment cmnt(masm_, "[ function compiled by full code generator");
125 125
126 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 126 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
127 127
128 #ifdef DEBUG 128 #ifdef DEBUG
129 if (strlen(FLAG_stop_at) > 0 && 129 if (strlen(FLAG_stop_at) > 0 &&
130 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 130 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
131 __ int3(); 131 __ int3();
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 } 301 }
302 302
303 303
304 void FullCodeGenerator::ClearAccumulator() { 304 void FullCodeGenerator::ClearAccumulator() {
305 __ Set(rax, 0); 305 __ Set(rax, 0);
306 } 306 }
307 307
308 308
309 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 309 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
310 __ movq(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); 310 __ movq(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
311 __ SmiAddConstant(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), 311 __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset),
312 Smi::FromInt(-delta)); 312 Smi::FromInt(-delta));
313 } 313 }
314 314
315 315
316 void FullCodeGenerator::EmitProfilingCounterReset() { 316 void FullCodeGenerator::EmitProfilingCounterReset() {
317 int reset_value = FLAG_interrupt_budget; 317 int reset_value = FLAG_interrupt_budget;
318 if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) { 318 if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) {
319 // Self-optimization is a one-off thing; if it fails, don't try again. 319 // Self-optimization is a one-off thing; if it fails, don't try again.
320 reset_value = Smi::kMaxValue; 320 reset_value = Smi::kMaxValue;
321 } 321 }
322 __ movq(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); 322 __ movq(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
323 __ movq(kScratchRegister, 323 __ movq(kScratchRegister,
324 reinterpret_cast<uint64_t>(Smi::FromInt(reset_value)), 324 reinterpret_cast<uint64_t>(Smi::FromInt(reset_value)),
325 RelocInfo::NONE64); 325 RelocInfo::NONE64);
326 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), 326 __ movq(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister);
327 kScratchRegister);
328 } 327 }
329 328
330 329
331 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 330 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
332 Label* back_edge_target) { 331 Label* back_edge_target) {
333 Comment cmnt(masm_, "[ Back edge bookkeeping"); 332 Comment cmnt(masm_, "[ Back edge bookkeeping");
334 Label ok; 333 Label ok;
335 334
336 int weight = 1; 335 int weight = 1;
337 if (FLAG_weighted_back_edges) { 336 if (FLAG_weighted_back_edges) {
338 ASSERT(back_edge_target->is_bound()); 337 ASSERT(back_edge_target->is_bound());
339 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 338 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
340 weight = Min(kMaxBackEdgeWeight, 339 weight = Min(kMaxBackEdgeWeight,
341 Max(1, distance / kBackEdgeDistanceUnit)); 340 Max(1, distance / kCodeSizeMultiplier));
342 } 341 }
343 EmitProfilingCounterDecrement(weight); 342 EmitProfilingCounterDecrement(weight);
344 __ j(positive, &ok, Label::kNear); 343 __ j(positive, &ok, Label::kNear);
345 InterruptStub stub; 344 InterruptStub stub;
346 __ CallStub(&stub); 345 __ CallStub(&stub);
347 346
348 // Record a mapping of this PC offset to the OSR id. This is used to find 347 // Record a mapping of this PC offset to the OSR id. This is used to find
349 // the AST id from the unoptimized code in order to use it as a key into 348 // the AST id from the unoptimized code in order to use it as a key into
350 // the deoptimization input data found in the optimized code. 349 // the deoptimization input data found in the optimized code.
351 RecordBackEdge(stmt->OsrEntryId()); 350 RecordBackEdge(stmt->OsrEntryId());
(...skipping 20 matching lines...) Expand all
372 __ CallRuntime(Runtime::kTraceExit, 1); 371 __ CallRuntime(Runtime::kTraceExit, 1);
373 } 372 }
374 if (FLAG_interrupt_at_exit || FLAG_self_optimization) { 373 if (FLAG_interrupt_at_exit || FLAG_self_optimization) {
375 // Pretend that the exit is a backwards jump to the entry. 374 // Pretend that the exit is a backwards jump to the entry.
376 int weight = 1; 375 int weight = 1;
377 if (info_->ShouldSelfOptimize()) { 376 if (info_->ShouldSelfOptimize()) {
378 weight = FLAG_interrupt_budget / FLAG_self_opt_count; 377 weight = FLAG_interrupt_budget / FLAG_self_opt_count;
379 } else if (FLAG_weighted_back_edges) { 378 } else if (FLAG_weighted_back_edges) {
380 int distance = masm_->pc_offset(); 379 int distance = masm_->pc_offset();
381 weight = Min(kMaxBackEdgeWeight, 380 weight = Min(kMaxBackEdgeWeight,
382 Max(1, distance / kBackEdgeDistanceUnit)); 381 Max(1, distance / kCodeSizeMultiplier));
383 } 382 }
384 EmitProfilingCounterDecrement(weight); 383 EmitProfilingCounterDecrement(weight);
385 Label ok; 384 Label ok;
386 __ j(positive, &ok, Label::kNear); 385 __ j(positive, &ok, Label::kNear);
387 __ push(rax); 386 __ push(rax);
388 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) { 387 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) {
389 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 388 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
390 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1); 389 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1);
391 } else { 390 } else {
392 InterruptStub stub; 391 InterruptStub stub;
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after
1121 __ jmp(&loop); 1120 __ jmp(&loop);
1122 1121
1123 __ bind(&no_descriptors); 1122 __ bind(&no_descriptors);
1124 __ addq(rsp, Immediate(kPointerSize)); 1123 __ addq(rsp, Immediate(kPointerSize));
1125 __ jmp(&exit); 1124 __ jmp(&exit);
1126 1125
1127 // We got a fixed array in register rax. Iterate through that. 1126 // We got a fixed array in register rax. Iterate through that.
1128 Label non_proxy; 1127 Label non_proxy;
1129 __ bind(&fixed_array); 1128 __ bind(&fixed_array);
1130 1129
1131 Handle<JSGlobalPropertyCell> cell = 1130 Handle<Cell> cell = isolate()->factory()->NewCell(
1132 isolate()->factory()->NewJSGlobalPropertyCell( 1131 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
1133 Handle<Object>( 1132 isolate()));
1134 Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
1135 isolate()));
1136 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell); 1133 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
1137 __ LoadHeapObject(rbx, cell); 1134 __ LoadHeapObject(rbx, cell);
1138 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), 1135 __ Move(FieldOperand(rbx, Cell::kValueOffset),
1139 Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)); 1136 Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker));
1140 1137
1141 __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check 1138 __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check
1142 __ movq(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object 1139 __ movq(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object
1143 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1140 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1144 __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx); 1141 __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx);
1145 __ j(above, &non_proxy); 1142 __ j(above, &non_proxy);
1146 __ Move(rbx, Smi::FromInt(0)); // Zero indicates proxy 1143 __ Move(rbx, Smi::FromInt(0)); // Zero indicates proxy
1147 __ bind(&non_proxy); 1144 __ bind(&non_proxy);
1148 __ push(rbx); // Smi 1145 __ push(rbx); // Smi
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after
1808 for (int i = 0; i < length; i++) { 1805 for (int i = 0; i < length; i++) {
1809 Expression* subexpr = subexprs->at(i); 1806 Expression* subexpr = subexprs->at(i);
1810 // If the subexpression is a literal or a simple materialized literal it 1807 // If the subexpression is a literal or a simple materialized literal it
1811 // is already set in the cloned array. 1808 // is already set in the cloned array.
1812 if (subexpr->AsLiteral() != NULL || 1809 if (subexpr->AsLiteral() != NULL ||
1813 CompileTimeValue::IsCompileTimeValue(subexpr)) { 1810 CompileTimeValue::IsCompileTimeValue(subexpr)) {
1814 continue; 1811 continue;
1815 } 1812 }
1816 1813
1817 if (!result_saved) { 1814 if (!result_saved) {
1818 __ push(rax); 1815 __ push(rax); // array literal
1816 __ Push(Smi::FromInt(expr->literal_index()));
1819 result_saved = true; 1817 result_saved = true;
1820 } 1818 }
1821 VisitForAccumulatorValue(subexpr); 1819 VisitForAccumulatorValue(subexpr);
1822 1820
1823 if (IsFastObjectElementsKind(constant_elements_kind)) { 1821 if (IsFastObjectElementsKind(constant_elements_kind)) {
1824 // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they 1822 // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
1825 // cannot transition and don't need to call the runtime stub. 1823 // cannot transition and don't need to call the runtime stub.
1826 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1824 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1827 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 1825 __ movq(rbx, Operand(rsp, kPointerSize)); // Copy of array literal.
1828 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 1826 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
1829 // Store the subexpression value in the array's elements. 1827 // Store the subexpression value in the array's elements.
1830 __ movq(FieldOperand(rbx, offset), result_register()); 1828 __ movq(FieldOperand(rbx, offset), result_register());
1831 // Update the write barrier for the array store. 1829 // Update the write barrier for the array store.
1832 __ RecordWriteField(rbx, offset, result_register(), rcx, 1830 __ RecordWriteField(rbx, offset, result_register(), rcx,
1833 kDontSaveFPRegs, 1831 kDontSaveFPRegs,
1834 EMIT_REMEMBERED_SET, 1832 EMIT_REMEMBERED_SET,
1835 INLINE_SMI_CHECK); 1833 INLINE_SMI_CHECK);
1836 } else { 1834 } else {
1837 // Store the subexpression value in the array's elements. 1835 // Store the subexpression value in the array's elements.
1838 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal.
1839 __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset));
1840 __ Move(rcx, Smi::FromInt(i)); 1836 __ Move(rcx, Smi::FromInt(i));
1841 __ Move(rdx, Smi::FromInt(expr->literal_index()));
1842 StoreArrayLiteralElementStub stub; 1837 StoreArrayLiteralElementStub stub;
1843 __ CallStub(&stub); 1838 __ CallStub(&stub);
1844 } 1839 }
1845 1840
1846 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); 1841 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1847 } 1842 }
1848 1843
1849 if (result_saved) { 1844 if (result_saved) {
1845 __ addq(rsp, Immediate(kPointerSize)); // literal index
1850 context()->PlugTOS(); 1846 context()->PlugTOS();
1851 } else { 1847 } else {
1852 context()->Plug(rax); 1848 context()->Plug(rax);
1853 } 1849 }
1854 } 1850 }
1855 1851
1856 1852
1857 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1853 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1858 Comment cmnt(masm_, "[ Assignment"); 1854 Comment cmnt(masm_, "[ Assignment");
1859 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1855 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1967 } 1963 }
1968 1964
1969 1965
1970 void FullCodeGenerator::VisitYield(Yield* expr) { 1966 void FullCodeGenerator::VisitYield(Yield* expr) {
1971 Comment cmnt(masm_, "[ Yield"); 1967 Comment cmnt(masm_, "[ Yield");
1972 // Evaluate yielded value first; the initial iterator definition depends on 1968 // Evaluate yielded value first; the initial iterator definition depends on
1973 // this. It stays on the stack while we update the iterator. 1969 // this. It stays on the stack while we update the iterator.
1974 VisitForStackValue(expr->expression()); 1970 VisitForStackValue(expr->expression());
1975 1971
1976 switch (expr->yield_kind()) { 1972 switch (expr->yield_kind()) {
1977 case Yield::INITIAL: 1973 case Yield::SUSPEND:
1978 case Yield::SUSPEND: { 1974 // Pop value from top-of-stack slot; box result into result register.
1975 EmitCreateIteratorResult(false);
1976 __ push(result_register());
1977 // Fall through.
1978 case Yield::INITIAL: {
1979 VisitForStackValue(expr->generator_object()); 1979 VisitForStackValue(expr->generator_object());
1980 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 1980 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1981 __ movq(context_register(), 1981 __ movq(context_register(),
1982 Operand(rbp, StandardFrameConstants::kContextOffset)); 1982 Operand(rbp, StandardFrameConstants::kContextOffset));
1983 1983
1984 Label resume; 1984 Label resume;
1985 __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex); 1985 __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex);
1986 __ j(not_equal, &resume); 1986 __ j(not_equal, &resume);
1987 if (expr->yield_kind() == Yield::SUSPEND) { 1987 __ pop(result_register());
1988 EmitReturnIteratorResult(false); 1988 EmitReturnSequence();
1989 } else {
1990 __ pop(result_register());
1991 EmitReturnSequence();
1992 }
1993 1989
1994 __ bind(&resume); 1990 __ bind(&resume);
1995 context()->Plug(result_register()); 1991 context()->Plug(result_register());
1996 break; 1992 break;
1997 } 1993 }
1998 1994
1999 case Yield::FINAL: { 1995 case Yield::FINAL: {
2000 VisitForAccumulatorValue(expr->generator_object()); 1996 VisitForAccumulatorValue(expr->generator_object());
2001 __ Move(FieldOperand(result_register(), 1997 __ Move(FieldOperand(result_register(),
2002 JSGeneratorObject::kContinuationOffset), 1998 JSGeneratorObject::kContinuationOffset),
2003 Smi::FromInt(JSGeneratorObject::kGeneratorClosed)); 1999 Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
2004 EmitReturnIteratorResult(true); 2000 // Pop value from top-of-stack slot, box result into result register.
2001 EmitCreateIteratorResult(true);
2002 EmitUnwindBeforeReturn();
2003 EmitReturnSequence();
2005 break; 2004 break;
2006 } 2005 }
2007 2006
2008 case Yield::DELEGATING: { 2007 case Yield::DELEGATING: {
2009 VisitForStackValue(expr->generator_object()); 2008 VisitForStackValue(expr->generator_object());
2010 2009
2011 // Initial stack layout is as follows: 2010 // Initial stack layout is as follows:
2012 // [sp + 1 * kPointerSize] iter 2011 // [sp + 1 * kPointerSize] iter
2013 // [sp + 0 * kPointerSize] g 2012 // [sp + 0 * kPointerSize] g
2014 2013
2015 Label l_catch, l_try, l_resume, l_next, l_call, l_loop; 2014 Label l_catch, l_try, l_resume, l_next, l_call, l_loop;
2016 // Initial send value is undefined. 2015 // Initial send value is undefined.
2017 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 2016 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2018 __ jmp(&l_next); 2017 __ jmp(&l_next);
2019 2018
2020 // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; } 2019 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
2021 __ bind(&l_catch); 2020 __ bind(&l_catch);
2022 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 2021 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
2023 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); // iter 2022 __ LoadRoot(rcx, Heap::kthrow_stringRootIndex); // "throw"
2024 __ push(rcx); // iter 2023 __ push(rcx);
2024 __ push(Operand(rsp, 2 * kPointerSize)); // iter
2025 __ push(rax); // exception 2025 __ push(rax); // exception
2026 __ movq(rax, rcx); // iter
2027 __ LoadRoot(rcx, Heap::kthrow_stringRootIndex); // "throw"
2028 Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize();
2029 CallIC(throw_ic); // iter.throw in rax
2030 __ jmp(&l_call); 2026 __ jmp(&l_call);
2031 2027
2032 // try { received = yield result.value } 2028 // try { received = %yield result }
2029 // Shuffle the received result above a try handler and yield it without
2030 // re-boxing.
2033 __ bind(&l_try); 2031 __ bind(&l_try);
2034 __ pop(rax); // result.value 2032 __ pop(rax); // result
2035 __ PushTryHandler(StackHandler::CATCH, expr->index()); 2033 __ PushTryHandler(StackHandler::CATCH, expr->index());
2036 const int handler_size = StackHandlerConstants::kSize; 2034 const int handler_size = StackHandlerConstants::kSize;
2037 __ push(rax); // result.value 2035 __ push(rax); // result
2038 __ push(Operand(rsp, (0 + 1) * kPointerSize + handler_size)); // g 2036 __ push(Operand(rsp, (0 + 1) * kPointerSize + handler_size)); // g
2039 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2037 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2040 __ movq(context_register(), 2038 __ movq(context_register(),
2041 Operand(rbp, StandardFrameConstants::kContextOffset)); 2039 Operand(rbp, StandardFrameConstants::kContextOffset));
2042 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 2040 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
2043 __ j(not_equal, &l_resume); 2041 __ j(not_equal, &l_resume);
2044 EmitReturnIteratorResult(false); 2042 __ pop(rax); // result
2043 EmitReturnSequence();
2045 __ bind(&l_resume); // received in rax 2044 __ bind(&l_resume); // received in rax
2046 __ PopTryHandler(); 2045 __ PopTryHandler();
2047 2046
2048 // receiver = iter; f = iter.next; arg = received; 2047 // receiver = iter; f = 'next'; arg = received;
2049 __ bind(&l_next); 2048 __ bind(&l_next);
2050 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); // iter 2049 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next"
2051 __ push(rcx); // iter 2050 __ push(rcx);
2051 __ push(Operand(rsp, 2 * kPointerSize)); // iter
2052 __ push(rax); // received 2052 __ push(rax); // received
2053 __ movq(rax, rcx); // iter
2054 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next"
2055 Handle<Code> next_ic = isolate()->builtins()->LoadIC_Initialize();
2056 CallIC(next_ic); // iter.next in rax
2057 2053
2058 // result = f.call(receiver, arg); 2054 // result = receiver[f](arg);
2059 __ bind(&l_call); 2055 __ bind(&l_call);
2060 Label l_call_runtime; 2056 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1);
2061 __ JumpIfSmi(rax, &l_call_runtime); 2057 CallIC(ic);
2062 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2063 __ j(not_equal, &l_call_runtime);
2064 __ movq(rdi, rax);
2065 ParameterCount count(1);
2066 __ InvokeFunction(rdi, count, CALL_FUNCTION,
2067 NullCallWrapper(), CALL_AS_METHOD);
2068 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2058 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2069 __ jmp(&l_loop); 2059 __ Drop(1); // The key is still on the stack; drop it.
2070 __ bind(&l_call_runtime);
2071 __ push(rax);
2072 __ CallRuntime(Runtime::kCall, 3);
2073 2060
2074 // val = result.value; if (!result.done) goto l_try; 2061 // if (!result.done) goto l_try;
2075 __ bind(&l_loop); 2062 __ bind(&l_loop);
2076 // result.value
2077 __ push(rax); // save result 2063 __ push(rax); // save result
2078 __ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value"
2079 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
2080 CallIC(value_ic); // result.value in rax
2081 __ pop(rbx); // result
2082 __ push(rax); // result.value
2083 __ movq(rax, rbx); // result
2084 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done" 2064 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done"
2085 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); 2065 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
2086 CallIC(done_ic); // result.done in rax 2066 CallIC(done_ic); // result.done in rax
2087 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 2067 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2088 CallIC(bool_ic); 2068 CallIC(bool_ic);
2089 __ testq(result_register(), result_register()); 2069 __ testq(result_register(), result_register());
2090 __ j(zero, &l_try); 2070 __ j(zero, &l_try);
2091 2071
2092 // result.value 2072 // result.value
2093 __ pop(rax); // result.value 2073 __ pop(rax); // result
2074 __ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value"
2075 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
2076 CallIC(value_ic); // result.value in rax
2094 context()->DropAndPlug(2, rax); // drop iter and g 2077 context()->DropAndPlug(2, rax); // drop iter and g
2095 break; 2078 break;
2096 } 2079 }
2097 } 2080 }
2098 } 2081 }
2099 2082
2100 2083
2101 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, 2084 void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
2102 Expression *value, 2085 Expression *value,
2103 JSGeneratorObject::ResumeMode resume_mode) { 2086 JSGeneratorObject::ResumeMode resume_mode) {
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2188 // Throw error if we attempt to operate on a running generator. 2171 // Throw error if we attempt to operate on a running generator.
2189 __ bind(&wrong_state); 2172 __ bind(&wrong_state);
2190 __ push(rbx); 2173 __ push(rbx);
2191 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); 2174 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
2192 2175
2193 __ bind(&done); 2176 __ bind(&done);
2194 context()->Plug(result_register()); 2177 context()->Plug(result_register());
2195 } 2178 }
2196 2179
2197 2180
2198 void FullCodeGenerator::EmitReturnIteratorResult(bool done) { 2181 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
2199 Label gc_required; 2182 Label gc_required;
2200 Label allocated; 2183 Label allocated;
2201 2184
2202 Handle<Map> map(isolate()->native_context()->generator_result_map()); 2185 Handle<Map> map(isolate()->native_context()->generator_result_map());
2203 2186
2204 __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT); 2187 __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT);
2188 __ jmp(&allocated);
2189
2190 __ bind(&gc_required);
2191 __ Push(Smi::FromInt(map->instance_size()));
2192 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2193 __ movq(context_register(),
2194 Operand(rbp, StandardFrameConstants::kContextOffset));
2205 2195
2206 __ bind(&allocated); 2196 __ bind(&allocated);
2207 __ Move(rbx, map); 2197 __ Move(rbx, map);
2208 __ pop(rcx); 2198 __ pop(rcx);
2209 __ Move(rdx, isolate()->factory()->ToBoolean(done)); 2199 __ Move(rdx, isolate()->factory()->ToBoolean(done));
2210 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); 2200 ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
2211 __ movq(FieldOperand(rax, HeapObject::kMapOffset), rbx); 2201 __ movq(FieldOperand(rax, HeapObject::kMapOffset), rbx);
2212 __ Move(FieldOperand(rax, JSObject::kPropertiesOffset), 2202 __ Move(FieldOperand(rax, JSObject::kPropertiesOffset),
2213 isolate()->factory()->empty_fixed_array()); 2203 isolate()->factory()->empty_fixed_array());
2214 __ Move(FieldOperand(rax, JSObject::kElementsOffset), 2204 __ Move(FieldOperand(rax, JSObject::kElementsOffset),
2215 isolate()->factory()->empty_fixed_array()); 2205 isolate()->factory()->empty_fixed_array());
2216 __ movq(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset), 2206 __ movq(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset),
2217 rcx); 2207 rcx);
2218 __ movq(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset), 2208 __ movq(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset),
2219 rdx); 2209 rdx);
2220 2210
2221 // Only the value field needs a write barrier, as the other values are in the 2211 // Only the value field needs a write barrier, as the other values are in the
2222 // root set. 2212 // root set.
2223 __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset, 2213 __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset,
2224 rcx, rdx, kDontSaveFPRegs); 2214 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 } 2215 }
2246 2216
2247 2217
2248 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 2218 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2249 SetSourcePosition(prop->position()); 2219 SetSourcePosition(prop->position());
2250 Literal* key = prop->key()->AsLiteral(); 2220 Literal* key = prop->key()->AsLiteral();
2251 __ Move(rcx, key->handle()); 2221 __ Move(rcx, key->handle());
2252 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2222 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2253 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); 2223 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
2254 } 2224 }
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
2613 VisitForStackValue(args->at(i)); 2583 VisitForStackValue(args->at(i));
2614 } 2584 }
2615 } 2585 }
2616 // Record source position for debugger. 2586 // Record source position for debugger.
2617 SetSourcePosition(expr->position()); 2587 SetSourcePosition(expr->position());
2618 2588
2619 // Record call targets in unoptimized code. 2589 // Record call targets in unoptimized code.
2620 flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET); 2590 flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
2621 Handle<Object> uninitialized = 2591 Handle<Object> uninitialized =
2622 TypeFeedbackCells::UninitializedSentinel(isolate()); 2592 TypeFeedbackCells::UninitializedSentinel(isolate());
2623 Handle<JSGlobalPropertyCell> cell = 2593 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
2624 isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
2625 RecordTypeFeedbackCell(expr->CallFeedbackId(), cell); 2594 RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
2626 __ Move(rbx, cell); 2595 __ Move(rbx, cell);
2627 2596
2628 CallFunctionStub stub(arg_count, flags); 2597 CallFunctionStub stub(arg_count, flags);
2629 __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2598 __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2630 __ CallStub(&stub, expr->CallFeedbackId()); 2599 __ CallStub(&stub, expr->CallFeedbackId());
2631 RecordJSReturnSite(expr); 2600 RecordJSReturnSite(expr);
2632 // Restore context register. 2601 // Restore context register.
2633 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2602 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2634 // Discard the function left on TOS. 2603 // Discard the function left on TOS.
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
2797 // constructor invocation. 2766 // constructor invocation.
2798 SetSourcePosition(expr->position()); 2767 SetSourcePosition(expr->position());
2799 2768
2800 // Load function and argument count into rdi and rax. 2769 // Load function and argument count into rdi and rax.
2801 __ Set(rax, arg_count); 2770 __ Set(rax, arg_count);
2802 __ movq(rdi, Operand(rsp, arg_count * kPointerSize)); 2771 __ movq(rdi, Operand(rsp, arg_count * kPointerSize));
2803 2772
2804 // Record call targets in unoptimized code, but not in the snapshot. 2773 // Record call targets in unoptimized code, but not in the snapshot.
2805 Handle<Object> uninitialized = 2774 Handle<Object> uninitialized =
2806 TypeFeedbackCells::UninitializedSentinel(isolate()); 2775 TypeFeedbackCells::UninitializedSentinel(isolate());
2807 Handle<JSGlobalPropertyCell> cell = 2776 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
2808 isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
2809 RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell); 2777 RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
2810 __ Move(rbx, cell); 2778 __ Move(rbx, cell);
2811 2779
2812 CallConstructStub stub(RECORD_CALL_TARGET); 2780 CallConstructStub stub(RECORD_CALL_TARGET);
2813 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); 2781 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL);
2814 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 2782 PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2815 context()->Plug(rax); 2783 context()->Plug(rax);
2816 } 2784 }
2817 2785
2818 2786
(...skipping 2093 matching lines...) Expand 10 before | Expand all | Expand 10 after
4912 *context_length = 0; 4880 *context_length = 0;
4913 return previous_; 4881 return previous_;
4914 } 4882 }
4915 4883
4916 4884
4917 #undef __ 4885 #undef __
4918 4886
4919 } } // namespace v8::internal 4887 } } // namespace v8::internal
4920 4888
4921 #endif // V8_TARGET_ARCH_X64 4889 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698