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

Side by Side Diff: src/a64/full-codegen-a64.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/a64/code-stubs-a64.cc ('k') | src/a64/ic-a64.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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 // - fp: our caller's frame pointer. 122 // - fp: our caller's frame pointer.
123 // - jssp: stack pointer. 123 // - jssp: stack pointer.
124 // - lr: return address. 124 // - lr: return address.
125 // 125 //
126 // The function builds a JS frame. See JavaScriptFrameConstants in 126 // The function builds a JS frame. See JavaScriptFrameConstants in
127 // frames-arm.h for its layout. 127 // frames-arm.h for its layout.
128 void FullCodeGenerator::Generate() { 128 void FullCodeGenerator::Generate() {
129 CompilationInfo* info = info_; 129 CompilationInfo* info = info_;
130 handler_table_ = 130 handler_table_ =
131 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 131 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
132 profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell( 132 profiling_counter_ = isolate()->factory()->NewCell(
133 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 133 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
134 SetFunctionPosition(function()); 134 SetFunctionPosition(function());
135 Comment cmnt(masm_, "[ Function compiled by full code generator"); 135 Comment cmnt(masm_, "[ Function compiled by full code generator");
136 136
137 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 137 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
138 138
139 #ifdef DEBUG 139 #ifdef DEBUG
140 if (strlen(FLAG_stop_at) > 0 && 140 if (strlen(FLAG_stop_at) > 0 &&
141 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 141 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
142 __ Debug("stop-at", __LINE__, BREAK); 142 __ Debug("stop-at", __LINE__, BREAK);
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 316
317 317
318 void FullCodeGenerator::ClearAccumulator() { 318 void FullCodeGenerator::ClearAccumulator() {
319 __ Mov(x0, Operand(Smi::FromInt(0))); 319 __ Mov(x0, Operand(Smi::FromInt(0)));
320 } 320 }
321 321
322 322
323 // TODO(mcapewel): untested, ported as part of merge. 323 // TODO(mcapewel): untested, ported as part of merge.
324 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 324 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
325 __ Mov(x2, Operand(profiling_counter_)); 325 __ Mov(x2, Operand(profiling_counter_));
326 __ Ldr(x3, FieldMemOperand(x2, JSGlobalPropertyCell::kValueOffset)); 326 __ Ldr(x3, FieldMemOperand(x2, Cell::kValueOffset));
327 __ Subs(x3, x3, Operand(Smi::FromInt(delta))); 327 __ Subs(x3, x3, Operand(Smi::FromInt(delta)));
328 __ Str(x3, FieldMemOperand(x2, JSGlobalPropertyCell::kValueOffset)); 328 __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset));
329 } 329 }
330 330
331 331
332 // TODO(mcapewel): untested, ported as part of merge. 332 // TODO(mcapewel): untested, ported as part of merge.
333 void FullCodeGenerator::EmitProfilingCounterReset() { 333 void FullCodeGenerator::EmitProfilingCounterReset() {
334 int reset_value = FLAG_interrupt_budget; 334 int reset_value = FLAG_interrupt_budget;
335 if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) { 335 if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) {
336 // Self-optimization is a one-off thing. if it fails, don't try again. 336 // Self-optimization is a one-off thing. if it fails, don't try again.
337 reset_value = Smi::kMaxValue; 337 reset_value = Smi::kMaxValue;
338 } 338 }
339 if (isolate()->IsDebuggerActive()) { 339 if (isolate()->IsDebuggerActive()) {
340 // Detect debug break requests as soon as possible. 340 // Detect debug break requests as soon as possible.
341 reset_value = FLAG_interrupt_budget >> 4; 341 reset_value = FLAG_interrupt_budget >> 4;
342 } 342 }
343 __ Mov(x2, Operand(profiling_counter_)); 343 __ Mov(x2, Operand(profiling_counter_));
344 __ Mov(x3, Operand(Smi::FromInt(reset_value))); 344 __ Mov(x3, Operand(Smi::FromInt(reset_value)));
345 __ Str(x3, FieldMemOperand(x2, JSGlobalPropertyCell::kValueOffset)); 345 __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset));
346 } 346 }
347 347
348 348
349 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 349 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
350 Label* back_edge_target) { 350 Label* back_edge_target) {
351 ASSERT(jssp.Is(__ StackPointer())); 351 ASSERT(jssp.Is(__ StackPointer()));
352 Comment cmnt(masm_, "[ Back edge bookkeeping"); 352 Comment cmnt(masm_, "[ Back edge bookkeeping");
353 // Block literal pools whilst emitting back edge code. 353 // Block literal pools whilst emitting back edge code.
354 Assembler::BlockConstPoolScope block_const_pool(masm_); 354 Assembler::BlockConstPoolScope block_const_pool(masm_);
355 Label ok; 355 Label ok;
356 356
357 int weight = 1; 357 int weight = 1;
358 if (FLAG_weighted_back_edges) { 358 if (FLAG_weighted_back_edges) {
359 ASSERT(back_edge_target->is_bound()); 359 ASSERT(back_edge_target->is_bound());
360 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 360 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
361 weight = Min(kMaxBackEdgeWeight, 361 weight = Min(kMaxBackEdgeWeight,
362 Max(1, distance / kBackEdgeDistanceUnit)); 362 Max(1, distance / kCodeSizeMultiplier));
363 } 363 }
364 EmitProfilingCounterDecrement(weight); 364 EmitProfilingCounterDecrement(weight);
365 __ B(pl, &ok); 365 __ B(pl, &ok);
366 InterruptStub stub; 366 InterruptStub stub;
367 __ CallStub(&stub); 367 __ CallStub(&stub);
368 368
369 // TODO(all): Implement OSR/Crankshaft code. 369 // TODO(all): Implement OSR/Crankshaft code.
370 370
371 EmitProfilingCounterReset(); 371 EmitProfilingCounterReset();
372 372
(...skipping 23 matching lines...) Expand all
396 ASSERT(x0.Is(result_register())); 396 ASSERT(x0.Is(result_register()));
397 } 397 }
398 if (FLAG_interrupt_at_exit || FLAG_self_optimization) { 398 if (FLAG_interrupt_at_exit || FLAG_self_optimization) {
399 // Pretend that the exit is a backwards jump to the entry. 399 // Pretend that the exit is a backwards jump to the entry.
400 int weight = 1; 400 int weight = 1;
401 if (info_->ShouldSelfOptimize()) { 401 if (info_->ShouldSelfOptimize()) {
402 weight = FLAG_interrupt_budget / FLAG_self_opt_count; 402 weight = FLAG_interrupt_budget / FLAG_self_opt_count;
403 } else if (FLAG_weighted_back_edges) { 403 } else if (FLAG_weighted_back_edges) {
404 int distance = masm_->pc_offset(); 404 int distance = masm_->pc_offset();
405 weight = Min(kMaxBackEdgeWeight, 405 weight = Min(kMaxBackEdgeWeight,
406 Max(1, distance / kBackEdgeDistanceUnit)); 406 Max(1, distance / kCodeSizeMultiplier));
407 } 407 }
408 EmitProfilingCounterDecrement(weight); 408 EmitProfilingCounterDecrement(weight);
409 Label ok; 409 Label ok;
410 __ B(pl, &ok); 410 __ B(pl, &ok);
411 __ Push(x0); 411 __ Push(x0);
412 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) { 412 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) {
413 __ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 413 __ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
414 __ Push(x10); 414 __ Push(x10);
415 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1); 415 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1);
416 } else { 416 } else {
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 __ B(&loop); 1158 __ B(&loop);
1159 1159
1160 __ Bind(&no_descriptors); 1160 __ Bind(&no_descriptors);
1161 __ Drop(1); 1161 __ Drop(1);
1162 __ B(&exit); 1162 __ B(&exit);
1163 1163
1164 // We got a fixed array in register x0. Iterate through that. 1164 // We got a fixed array in register x0. Iterate through that.
1165 Label non_proxy; 1165 Label non_proxy;
1166 __ Bind(&fixed_array); 1166 __ Bind(&fixed_array);
1167 1167
1168 Handle<JSGlobalPropertyCell> cell = 1168 Handle<Cell> cell = isolate()->factory()->NewCell(
1169 isolate()->factory()->NewJSGlobalPropertyCell( 1169 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
1170 Handle<Object>( 1170 isolate()));
1171 Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
1172 isolate()));
1173 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell); 1171 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
1174 __ LoadHeapObject(x1, cell); 1172 __ LoadHeapObject(x1, cell);
1175 __ Mov(x10, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); 1173 __ Mov(x10, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
1176 __ Str(x10, FieldMemOperand(x1, JSGlobalPropertyCell::kValueOffset)); 1174 __ Str(x10, FieldMemOperand(x1, Cell::kValueOffset));
1177 1175
1178 __ Mov(x1, Operand(Smi::FromInt(1))); // Smi indicates slow check. 1176 __ Mov(x1, Operand(Smi::FromInt(1))); // Smi indicates slow check.
1179 __ Peek(x10, 0); // Get enumerated object. 1177 __ Peek(x10, 0); // Get enumerated object.
1180 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1178 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1181 // TODO(all): similar check was done already. Can we avoid it here? 1179 // TODO(all): similar check was done already. Can we avoid it here?
1182 __ JumpIfObjectType(x10, x11, x12, LAST_JS_PROXY_TYPE, &non_proxy, gt); 1180 __ JumpIfObjectType(x10, x11, x12, LAST_JS_PROXY_TYPE, &non_proxy, gt);
1183 // TODO(all): use csel here 1181 // TODO(all): use csel here
1184 __ Mov(x1, Operand(Smi::FromInt(0))); // Zero indicates proxy. 1182 __ Mov(x1, Operand(Smi::FromInt(0))); // Zero indicates proxy.
1185 __ Bind(&non_proxy); 1183 __ Bind(&non_proxy);
1186 __ Push(x1, x0); // Smi and array 1184 __ Push(x1, x0); // Smi and array
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
1827 Expression* subexpr = subexprs->at(i); 1825 Expression* subexpr = subexprs->at(i);
1828 // If the subexpression is a literal or a simple materialized literal it 1826 // If the subexpression is a literal or a simple materialized literal it
1829 // is already set in the cloned array. 1827 // is already set in the cloned array.
1830 if (subexpr->AsLiteral() != NULL || 1828 if (subexpr->AsLiteral() != NULL ||
1831 CompileTimeValue::IsCompileTimeValue(subexpr)) { 1829 CompileTimeValue::IsCompileTimeValue(subexpr)) {
1832 continue; 1830 continue;
1833 } 1831 }
1834 1832
1835 if (!result_saved) { 1833 if (!result_saved) {
1836 __ Push(x0); 1834 __ Push(x0);
1835 __ Push(Smi::FromInt(expr->literal_index()));
1837 result_saved = true; 1836 result_saved = true;
1838 } 1837 }
1839 VisitForAccumulatorValue(subexpr); 1838 VisitForAccumulatorValue(subexpr);
1840 1839
1841 if (IsFastObjectElementsKind(constant_elements_kind)) { 1840 if (IsFastObjectElementsKind(constant_elements_kind)) {
1842 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1841 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1843 __ Peek(x6, 0); // Copy of array literal. 1842 __ Peek(x6, kPointerSize); // Copy of array literal.
1844 __ Ldr(x1, FieldMemOperand(x6, JSObject::kElementsOffset)); 1843 __ Ldr(x1, FieldMemOperand(x6, JSObject::kElementsOffset));
1845 __ Str(result_register(), FieldMemOperand(x1, offset)); 1844 __ Str(result_register(), FieldMemOperand(x1, offset));
1846 // Update the write barrier for the array store. 1845 // Update the write barrier for the array store.
1847 __ RecordWriteField(x1, offset, result_register(), x10, 1846 __ RecordWriteField(x1, offset, result_register(), x10,
1848 kLRHasBeenSaved, kDontSaveFPRegs, 1847 kLRHasBeenSaved, kDontSaveFPRegs,
1849 EMIT_REMEMBERED_SET, INLINE_SMI_CHECK); 1848 EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
1850 } else { 1849 } else {
1851 __ Peek(x1, 0); // Copy of array literal.
1852 __ Ldr(x2, FieldMemOperand(x1, JSObject::kMapOffset));
1853 __ Mov(x3, Operand(Smi::FromInt(i))); 1850 __ Mov(x3, Operand(Smi::FromInt(i)));
1854 __ Mov(x4, Operand(Smi::FromInt(expr->literal_index())));
1855 StoreArrayLiteralElementStub stub; 1851 StoreArrayLiteralElementStub stub;
1856 __ CallStub(&stub); 1852 __ CallStub(&stub);
1857 } 1853 }
1858 1854
1859 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); 1855 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1860 } 1856 }
1861 1857
1862 if (result_saved) { 1858 if (result_saved) {
1859 __ Drop(1); // literal index
1863 context()->PlugTOS(); 1860 context()->PlugTOS();
1864 } else { 1861 } else {
1865 context()->Plug(x0); 1862 context()->Plug(x0);
1866 } 1863 }
1867 } 1864 }
1868 1865
1869 1866
1870 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1867 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1871 Comment cmnt(masm_, "[ Assignment"); 1868 Comment cmnt(masm_, "[ Assignment");
1872 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1869 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
2406 VisitForStackValue(args->at(i)); 2403 VisitForStackValue(args->at(i));
2407 } 2404 }
2408 } 2405 }
2409 // Record source position for debugger. 2406 // Record source position for debugger.
2410 SetSourcePosition(expr->position()); 2407 SetSourcePosition(expr->position());
2411 2408
2412 // Record call targets in unoptimized code. 2409 // Record call targets in unoptimized code.
2413 flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET); 2410 flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
2414 Handle<Object> uninitialized = 2411 Handle<Object> uninitialized =
2415 TypeFeedbackCells::UninitializedSentinel(isolate()); 2412 TypeFeedbackCells::UninitializedSentinel(isolate());
2416 Handle<JSGlobalPropertyCell> cell = 2413 Handle<Cell> cell =
2417 isolate()->factory()->NewJSGlobalPropertyCell(uninitialized); 2414 isolate()->factory()->NewCell(uninitialized);
2418 RecordTypeFeedbackCell(expr->CallFeedbackId(), cell); 2415 RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
2419 __ Mov(x2, Operand(cell)); 2416 __ Mov(x2, Operand(cell));
2420 2417
2421 CallFunctionStub stub(arg_count, flags); 2418 CallFunctionStub stub(arg_count, flags);
2422 __ Peek(x1, (arg_count + 1) * kXRegSizeInBytes); 2419 __ Peek(x1, (arg_count + 1) * kXRegSizeInBytes);
2423 __ CallStub(&stub, expr->CallFeedbackId()); 2420 __ CallStub(&stub, expr->CallFeedbackId());
2424 RecordJSReturnSite(expr); 2421 RecordJSReturnSite(expr);
2425 // Restore context register. 2422 // Restore context register.
2426 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2423 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2427 context()->DropAndPlug(1, x0); 2424 context()->DropAndPlug(1, x0);
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
2612 // constructor invocation. 2609 // constructor invocation.
2613 SetSourcePosition(expr->position()); 2610 SetSourcePosition(expr->position());
2614 2611
2615 // Load function and argument count into x1 and x0. 2612 // Load function and argument count into x1 and x0.
2616 __ Mov(x0, arg_count); 2613 __ Mov(x0, arg_count);
2617 __ Peek(x1, arg_count * kXRegSizeInBytes); 2614 __ Peek(x1, arg_count * kXRegSizeInBytes);
2618 2615
2619 // Record call targets in unoptimized code. 2616 // Record call targets in unoptimized code.
2620 Handle<Object> uninitialized = 2617 Handle<Object> uninitialized =
2621 TypeFeedbackCells::UninitializedSentinel(isolate()); 2618 TypeFeedbackCells::UninitializedSentinel(isolate());
2622 Handle<JSGlobalPropertyCell> cell = 2619 Handle<Cell> cell =
2623 isolate()->factory()->NewJSGlobalPropertyCell(uninitialized); 2620 isolate()->factory()->NewCell(uninitialized);
2624 RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell); 2621 RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
2625 __ Mov(x2, Operand(cell)); 2622 __ Mov(x2, Operand(cell));
2626 2623
2627 CallConstructStub stub(RECORD_CALL_TARGET); 2624 CallConstructStub stub(RECORD_CALL_TARGET);
2628 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); 2625 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL);
2629 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 2626 PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2630 context()->Plug(x0); 2627 context()->Plug(x0);
2631 } 2628 }
2632 2629
2633 2630
(...skipping 1894 matching lines...) Expand 10 before | Expand all | Expand 10 after
4528 } 4525 }
4529 4526
4530 4527
4531 void FullCodeGenerator::VisitYield(Yield* expr) { 4528 void FullCodeGenerator::VisitYield(Yield* expr) {
4532 Comment cmnt(masm_, "[ Yield"); 4529 Comment cmnt(masm_, "[ Yield");
4533 // Evaluate yielded value first; the initial iterator definition depends on 4530 // Evaluate yielded value first; the initial iterator definition depends on
4534 // this. It stays on the stack while we update the iterator. 4531 // this. It stays on the stack while we update the iterator.
4535 VisitForStackValue(expr->expression()); 4532 VisitForStackValue(expr->expression());
4536 4533
4537 switch (expr->yield_kind()) { 4534 switch (expr->yield_kind()) {
4538 case Yield::INITIAL: 4535 case Yield::SUSPEND:
4539 case Yield::SUSPEND: { 4536 // Pop value from top-of-stack slot; box result into result register.
4537 EmitCreateIteratorResult(false);
4538 __ Push(result_register());
4539 // Fall through.
4540 case Yield::INITIAL: {
4540 VisitForStackValue(expr->generator_object()); 4541 VisitForStackValue(expr->generator_object());
4541 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 4542 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
4542 __ Ldr(context_register(), 4543 __ Ldr(context_register(),
4543 MemOperand(fp, StandardFrameConstants::kContextOffset)); 4544 MemOperand(fp, StandardFrameConstants::kContextOffset));
4544 4545
4545 Label resume; 4546 Label resume;
4546 __ JumpIfNotRoot(result_register(), Heap::kTheHoleValueRootIndex, 4547 __ JumpIfNotRoot(result_register(), Heap::kTheHoleValueRootIndex,
4547 &resume); 4548 &resume);
4548 if (expr->yield_kind() == Yield::SUSPEND) { 4549 __ Pop(result_register());
4549 EmitReturnIteratorResult(false); 4550 EmitReturnSequence();
4550 } else {
4551 __ Pop(result_register());
4552 EmitReturnSequence();
4553 }
4554 4551
4555 __ Bind(&resume); 4552 __ Bind(&resume);
4556 context()->Plug(result_register()); 4553 context()->Plug(result_register());
4557 break; 4554 break;
4558 } 4555 }
4559 4556
4560 case Yield::FINAL: { 4557 case Yield::FINAL: {
4561 VisitForAccumulatorValue(expr->generator_object()); 4558 VisitForAccumulatorValue(expr->generator_object());
4562 __ Mov(x1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); 4559 __ Mov(x1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
4563 __ Str(x1, FieldMemOperand(result_register(), 4560 __ Str(x1, FieldMemOperand(result_register(),
4564 JSGeneratorObject::kContinuationOffset)); 4561 JSGeneratorObject::kContinuationOffset));
4565 EmitReturnIteratorResult(true); 4562 // Pop value from top-of-stack slot, box result into result register.
4563 EmitCreateIteratorResult(true);
4564 EmitUnwindBeforeReturn();
4565 EmitReturnSequence();
4566 break; 4566 break;
4567 } 4567 }
4568 4568
4569 case Yield::DELEGATING: { 4569 case Yield::DELEGATING: {
4570 VisitForStackValue(expr->generator_object()); 4570 VisitForStackValue(expr->generator_object());
4571 4571
4572 // Initial stack layout is as follows: 4572 // Initial stack layout is as follows:
4573 // [sp + 1 * kPointerSize] iter 4573 // [sp + 1 * kPointerSize] iter
4574 // [sp + 0 * kPointerSize] g 4574 // [sp + 0 * kPointerSize] g
4575 4575
4576 // TODO(jbramley): Tidy this up once the merge is done, using named 4576 // TODO(jbramley): Tidy this up once the merge is done, using named
4577 // registers and suchlike. The implementation changes a little by 4577 // registers and suchlike. The implementation changes a little by
4578 // bleeding_edge so I don't want to spend too much time on it now. 4578 // bleeding_edge so I don't want to spend too much time on it now.
4579 4579
4580 Label l_catch, l_try, l_resume, l_next, l_call, l_loop; 4580 Label l_catch, l_try, l_resume, l_next, l_call, l_loop;
4581 // Initial send value is undefined. 4581 // Initial send value is undefined.
4582 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); 4582 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
4583 __ B(&l_next); 4583 __ B(&l_next);
4584 4584
4585 // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; } 4585 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
4586 __ Bind(&l_catch); 4586 __ Bind(&l_catch);
4587 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 4587 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
4588 __ LoadRoot(x2, Heap::kthrow_stringRootIndex); // "throw"
4588 __ Peek(x3, 1 * kPointerSize); // iter 4589 __ Peek(x3, 1 * kPointerSize); // iter
4589 __ Push(x3); // iter 4590 __ Push(x3); // iter
4590 __ Push(x0); // exception 4591 __ Push(x0); // exception
4591 __ Mov(x0, x3); // iter
4592 __ LoadRoot(x2, Heap::kthrow_stringRootIndex); // "throw"
4593 Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize();
4594 CallIC(throw_ic); // iter.throw in x0
4595 __ B(&l_call); 4592 __ B(&l_call);
4596 4593
4597 // try { received = yield result.value } 4594 // try { received = %yield result }
4595 // Shuffle the received result above a try handler and yield it without
4596 // re-boxing.
4598 __ Bind(&l_try); 4597 __ Bind(&l_try);
4599 __ Pop(x0); // result.value 4598 __ Pop(x0); // result
4600 __ PushTryHandler(StackHandler::CATCH, expr->index()); 4599 __ PushTryHandler(StackHandler::CATCH, expr->index());
4601 const int handler_size = StackHandlerConstants::kSize; 4600 const int handler_size = StackHandlerConstants::kSize;
4602 __ Push(x0); // result.value 4601 __ Push(x0); // result
4603 __ Peek(x3, (1 * kPointerSize) + handler_size); // g 4602 __ Peek(x3, (1 * kPointerSize) + handler_size); // g
4604 __ Push(x3); // g 4603 __ Push(x3); // g
4605 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 4604 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
4606 __ Ldr(context_register(), 4605 __ Ldr(context_register(),
4607 MemOperand(fp, StandardFrameConstants::kContextOffset)); 4606 MemOperand(fp, StandardFrameConstants::kContextOffset));
4608 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &l_resume); 4607 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &l_resume);
4609 EmitReturnIteratorResult(false); 4608 __ Pop(x0); // result
4609 EmitReturnSequence();
4610 __ Bind(&l_resume); // received in x0 4610 __ Bind(&l_resume); // received in x0
4611 __ PopTryHandler(); 4611 __ PopTryHandler();
4612 4612
4613 // receiver = iter; f = iter.next; arg = received; 4613 // receiver = iter; f = 'next'; arg = received;
4614 __ Bind(&l_next); 4614 __ Bind(&l_next);
4615 __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next"
4615 __ Peek(x3, 1 * kPointerSize); // iter 4616 __ Peek(x3, 1 * kPointerSize); // iter
4616 __ Push(x3); // iter 4617 __ Push(x3); // iter
4617 __ Push(x0); // received 4618 __ Push(x0); // received
4618 __ Mov(x0, x3); // iter
4619 __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next"
4620 Handle<Code> next_ic = isolate()->builtins()->LoadIC_Initialize();
4621 CallIC(next_ic); // iter.next in r0
4622 4619
4623 // result = f.call(receiver, arg); 4620 // result = receiver[f](arg);
4624 __ Bind(&l_call); 4621 __ Bind(&l_call);
4625 Label l_call_runtime; 4622 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1);
4626 __ JumpIfSmi(x0, &l_call_runtime); 4623 CallIC(ic);
4627 __ JumpIfNotObjectType(x0, x1, x1, JS_FUNCTION_TYPE, &l_call_runtime);
4628 __ Mov(x1, x0);
4629 ParameterCount count(1);
4630 __ InvokeFunction(x1, count, CALL_FUNCTION,
4631 NullCallWrapper(), CALL_AS_METHOD);
4632 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4624 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4633 __ B(&l_loop);
4634 __ Bind(&l_call_runtime);
4635 __ Push(x0);
4636 __ CallRuntime(Runtime::kCall, 3);
4637 4625
4638 // val = result.value; if (!result.done) goto l_try; 4626 // if (!result.done) goto l_try;
4639 __ Bind(&l_loop); 4627 __ Bind(&l_loop);
4640 // result.value
4641 __ Push(x0); // save result 4628 __ Push(x0); // save result
4642 __ LoadRoot(x2, Heap::kvalue_stringRootIndex); // "value"
4643 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
4644 CallIC(value_ic); // result.value in x0
4645 __ Pop(x1); // result
4646 __ Push(x0); // result.value
4647 __ Mov(x0, x1); // result
4648 __ LoadRoot(x2, Heap::kdone_stringRootIndex); // "done" 4629 __ LoadRoot(x2, Heap::kdone_stringRootIndex); // "done"
4649 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); 4630 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
4650 CallIC(done_ic); // result.done in x0 4631 CallIC(done_ic); // result.done in x0
4651 // The ToBooleanStub argument (result.done) is in x0. 4632 // The ToBooleanStub argument (result.done) is in x0.
4652 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 4633 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
4653 CallIC(bool_ic); 4634 CallIC(bool_ic);
4654 __ Cbz(x0, &l_try); 4635 __ Cbz(x0, &l_try);
4655 4636
4656 // result.value 4637 // result.value
4657 __ Pop(x0); // result.value 4638 __ Pop(x0); // result
4639 __ LoadRoot(x2, Heap::kvalue_stringRootIndex); // "value"
4640 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
4641 CallIC(value_ic); // result.value in x0
4658 context()->DropAndPlug(2, x0); // drop iter and g 4642 context()->DropAndPlug(2, x0); // drop iter and g
4659 break; 4643 break;
4660 } 4644 }
4661 } 4645 }
4662 } 4646 }
4663 4647
4664 4648
4665 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, 4649 void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
4666 Expression *value, 4650 Expression *value,
4667 JSGeneratorObject::ResumeMode resume_mode) { 4651 JSGeneratorObject::ResumeMode resume_mode) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
4778 // Throw error if we attempt to operate on a running generator. 4762 // Throw error if we attempt to operate on a running generator.
4779 __ Bind(&wrong_state); 4763 __ Bind(&wrong_state);
4780 __ Push(generator_object); 4764 __ Push(generator_object);
4781 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); 4765 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
4782 4766
4783 __ Bind(&done); 4767 __ Bind(&done);
4784 context()->Plug(result_register()); 4768 context()->Plug(result_register());
4785 } 4769 }
4786 4770
4787 4771
4788 void FullCodeGenerator::EmitReturnIteratorResult(bool done) { 4772 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
4789 Label gc_required; 4773 Label gc_required;
4790 Label allocated; 4774 Label allocated;
4791 4775
4792 Handle<Map> map(isolate()->native_context()->generator_result_map()); 4776 Handle<Map> map(isolate()->native_context()->generator_result_map());
4793 4777
4794 // Allocate and populate an object with this form: { value: VAL, done: DONE } 4778 // Allocate and populate an object with this form: { value: VAL, done: DONE }
4795 4779
4796 Register result = x0; 4780 Register result = x0;
4797 __ Allocate(map->instance_size(), result, x10, x11, &gc_required, TAG_OBJECT); 4781 __ Allocate(map->instance_size(), result, x10, x11, &gc_required, TAG_OBJECT);
4782 __ B(&allocated);
4783
4784 __ Bind(&gc_required);
4785 __ Push(Smi::FromInt(map->instance_size()));
4786 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
4787 __ Ldr(context_register(),
4788 MemOperand(fp, StandardFrameConstants::kContextOffset));
4789
4798 __ Bind(&allocated); 4790 __ Bind(&allocated);
4799
4800 Register map_reg = x1; 4791 Register map_reg = x1;
4801 Register result_value = x2; 4792 Register result_value = x2;
4802 Register boolean_done = x3; 4793 Register boolean_done = x3;
4803 Register empty_fixed_array = x4; 4794 Register empty_fixed_array = x4;
4804 __ Mov(map_reg, Operand(map)); 4795 __ Mov(map_reg, Operand(map));
4805 __ Pop(result_value); 4796 __ Pop(result_value);
4806 __ Mov(boolean_done, Operand(isolate()->factory()->ToBoolean(done))); 4797 __ Mov(boolean_done, Operand(isolate()->factory()->ToBoolean(done)));
4807 __ Mov(empty_fixed_array, Operand(isolate()->factory()->empty_fixed_array())); 4798 __ Mov(empty_fixed_array, Operand(isolate()->factory()->empty_fixed_array()));
4808 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); 4799 ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
4809 // TODO(jbramley): Use Stp if possible. 4800 // TODO(jbramley): Use Stp if possible.
4810 __ Str(map_reg, FieldMemOperand(result, HeapObject::kMapOffset)); 4801 __ Str(map_reg, FieldMemOperand(result, HeapObject::kMapOffset));
4811 __ Str(empty_fixed_array, 4802 __ Str(empty_fixed_array,
4812 FieldMemOperand(result, JSObject::kPropertiesOffset)); 4803 FieldMemOperand(result, JSObject::kPropertiesOffset));
4813 __ Str(empty_fixed_array, FieldMemOperand(result, JSObject::kElementsOffset)); 4804 __ Str(empty_fixed_array, FieldMemOperand(result, JSObject::kElementsOffset));
4814 __ Str(result_value, 4805 __ Str(result_value,
4815 FieldMemOperand(result, 4806 FieldMemOperand(result,
4816 JSGeneratorObject::kResultValuePropertyOffset)); 4807 JSGeneratorObject::kResultValuePropertyOffset));
4817 __ Str(boolean_done, 4808 __ Str(boolean_done,
4818 FieldMemOperand(result, 4809 FieldMemOperand(result,
4819 JSGeneratorObject::kResultDonePropertyOffset)); 4810 JSGeneratorObject::kResultDonePropertyOffset));
4820 4811
4821 // Only the value field needs a write barrier, as the other values are in the 4812 // Only the value field needs a write barrier, as the other values are in the
4822 // root set. 4813 // root set.
4823 __ RecordWriteField(result, JSGeneratorObject::kResultValuePropertyOffset, 4814 __ RecordWriteField(result, JSGeneratorObject::kResultValuePropertyOffset,
4824 x10, x11, kLRHasBeenSaved, kDontSaveFPRegs); 4815 x10, x11, kLRHasBeenSaved, kDontSaveFPRegs);
4825
4826 if (done) {
4827 // Exit all nested statements.
4828 NestedStatement* current = nesting_stack_;
4829 int stack_depth = 0;
4830 int context_length = 0;
4831 while (current != NULL) {
4832 current = current->Exit(&stack_depth, &context_length);
4833 }
4834 __ Drop(stack_depth);
4835 }
4836
4837 EmitReturnSequence();
4838
4839 __ Bind(&gc_required);
4840 __ Push(Smi::FromInt(map->instance_size()));
4841 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
4842 __ Ldr(context_register(),
4843 MemOperand(fp, StandardFrameConstants::kContextOffset));
4844 __ B(&allocated);
4845 } 4816 }
4846 4817
4847 4818
4848 // TODO(all): I don't like this method. 4819 // TODO(all): I don't like this method.
4849 // It seems to me that in too many places x0 is used in place of this. 4820 // It seems to me that in too many places x0 is used in place of this.
4850 // Also, this function is not suitable for all places where x0 should be 4821 // Also, this function is not suitable for all places where x0 should be
4851 // abstracted (eg. when used as an argument). But some places assume that the 4822 // abstracted (eg. when used as an argument). But some places assume that the
4852 // first argument register is x0, and use this function instead. 4823 // first argument register is x0, and use this function instead.
4853 // Considering that most of the register allocation is hard-coded in the 4824 // Considering that most of the register allocation is hard-coded in the
4854 // FullCodeGen, that it is unlikely we will need to change it extensively, and 4825 // FullCodeGen, that it is unlikely we will need to change it extensively, and
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
4992 return previous_; 4963 return previous_;
4993 } 4964 }
4994 4965
4995 4966
4996 #undef __ 4967 #undef __
4997 4968
4998 4969
4999 } } // namespace v8::internal 4970 } } // namespace v8::internal
5000 4971
5001 #endif // V8_TARGET_ARCH_A64 4972 #endif // V8_TARGET_ARCH_A64
OLDNEW
« no previous file with comments | « src/a64/code-stubs-a64.cc ('k') | src/a64/ic-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698