| 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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |