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

Side by Side Diff: src/arm64/lithium-codegen-arm64.cc

Issue 262533006: ARM64: use jssp for stack slots (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 7 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/arm64/lithium-codegen-arm64.h ('k') | no next file » | 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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "v8.h" 5 #include "v8.h"
6 6
7 #include "arm64/lithium-codegen-arm64.h" 7 #include "arm64/lithium-codegen-arm64.h"
8 #include "arm64/lithium-gap-resolver-arm64.h" 8 #include "arm64/lithium-gap-resolver-arm64.h"
9 #include "code-stubs.h" 9 #include "code-stubs.h"
10 #include "stub-cache.h" 10 #include "stub-cache.h"
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 402
403 403
404 void LCodeGen::DoCallFunction(LCallFunction* instr) { 404 void LCodeGen::DoCallFunction(LCallFunction* instr) {
405 ASSERT(ToRegister(instr->context()).is(cp)); 405 ASSERT(ToRegister(instr->context()).is(cp));
406 ASSERT(ToRegister(instr->function()).Is(x1)); 406 ASSERT(ToRegister(instr->function()).Is(x1));
407 ASSERT(ToRegister(instr->result()).Is(x0)); 407 ASSERT(ToRegister(instr->result()).Is(x0));
408 408
409 int arity = instr->arity(); 409 int arity = instr->arity();
410 CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags()); 410 CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags());
411 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 411 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
412 after_push_argument_ = false;
412 } 413 }
413 414
414 415
415 void LCodeGen::DoCallNew(LCallNew* instr) { 416 void LCodeGen::DoCallNew(LCallNew* instr) {
416 ASSERT(ToRegister(instr->context()).is(cp)); 417 ASSERT(ToRegister(instr->context()).is(cp));
417 ASSERT(instr->IsMarkedAsCall()); 418 ASSERT(instr->IsMarkedAsCall());
418 ASSERT(ToRegister(instr->constructor()).is(x1)); 419 ASSERT(ToRegister(instr->constructor()).is(x1));
419 420
420 __ Mov(x0, instr->arity()); 421 __ Mov(x0, instr->arity());
421 // No cell in x2 for construct type feedback in optimized code. 422 // No cell in x2 for construct type feedback in optimized code.
422 __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); 423 __ LoadRoot(x2, Heap::kUndefinedValueRootIndex);
423 424
424 CallConstructStub stub(isolate(), NO_CALL_FUNCTION_FLAGS); 425 CallConstructStub stub(isolate(), NO_CALL_FUNCTION_FLAGS);
425 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); 426 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
427 after_push_argument_ = false;
426 428
427 ASSERT(ToRegister(instr->result()).is(x0)); 429 ASSERT(ToRegister(instr->result()).is(x0));
428 } 430 }
429 431
430 432
431 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { 433 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
432 ASSERT(instr->IsMarkedAsCall()); 434 ASSERT(instr->IsMarkedAsCall());
433 ASSERT(ToRegister(instr->context()).is(cp)); 435 ASSERT(ToRegister(instr->context()).is(cp));
434 ASSERT(ToRegister(instr->constructor()).is(x1)); 436 ASSERT(ToRegister(instr->constructor()).is(x1));
435 437
(...skipping 27 matching lines...) Expand all
463 __ Bind(&packed_case); 465 __ Bind(&packed_case);
464 } 466 }
465 467
466 ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode); 468 ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode);
467 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); 469 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
468 __ Bind(&done); 470 __ Bind(&done);
469 } else { 471 } else {
470 ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode); 472 ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
471 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); 473 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
472 } 474 }
475 after_push_argument_ = false;
473 476
474 ASSERT(ToRegister(instr->result()).is(x0)); 477 ASSERT(ToRegister(instr->result()).is(x0));
475 } 478 }
476 479
477 480
478 void LCodeGen::CallRuntime(const Runtime::Function* function, 481 void LCodeGen::CallRuntime(const Runtime::Function* function,
479 int num_arguments, 482 int num_arguments,
480 LInstruction* instr, 483 LInstruction* instr,
481 SaveFPRegsMode save_doubles) { 484 SaveFPRegsMode save_doubles) {
482 ASSERT(instr != NULL); 485 ASSERT(instr != NULL);
483 486
484 __ CallRuntime(function, num_arguments, save_doubles); 487 __ CallRuntime(function, num_arguments, save_doubles);
485 488
486 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 489 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
487 } 490 }
488 491
489 492
490 void LCodeGen::LoadContextFromDeferred(LOperand* context) { 493 void LCodeGen::LoadContextFromDeferred(LOperand* context) {
491 if (context->IsRegister()) { 494 if (context->IsRegister()) {
492 __ Mov(cp, ToRegister(context)); 495 __ Mov(cp, ToRegister(context));
493 } else if (context->IsStackSlot()) { 496 } else if (context->IsStackSlot()) {
494 __ Ldr(cp, ToMemOperand(context)); 497 __ Ldr(cp, ToMemOperand(context, kMustUseFramePointer));
495 } else if (context->IsConstantOperand()) { 498 } else if (context->IsConstantOperand()) {
496 HConstant* constant = 499 HConstant* constant =
497 chunk_->LookupConstant(LConstantOperand::cast(context)); 500 chunk_->LookupConstant(LConstantOperand::cast(context));
498 __ LoadHeapObject(cp, 501 __ LoadHeapObject(cp,
499 Handle<HeapObject>::cast(constant->handle(isolate()))); 502 Handle<HeapObject>::cast(constant->handle(isolate())));
500 } else { 503 } else {
501 UNREACHABLE(); 504 UNREACHABLE();
502 } 505 }
503 } 506 }
504 507
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after
1225 return Operand(0); 1228 return Operand(0);
1226 } 1229 }
1227 1230
1228 1231
1229 static ptrdiff_t ArgumentsOffsetWithoutFrame(ptrdiff_t index) { 1232 static ptrdiff_t ArgumentsOffsetWithoutFrame(ptrdiff_t index) {
1230 ASSERT(index < 0); 1233 ASSERT(index < 0);
1231 return -(index + 1) * kPointerSize; 1234 return -(index + 1) * kPointerSize;
1232 } 1235 }
1233 1236
1234 1237
1235 MemOperand LCodeGen::ToMemOperand(LOperand* op) const { 1238 MemOperand LCodeGen::ToMemOperand(LOperand* op, StackMode stack_mode) const {
1236 ASSERT(op != NULL); 1239 ASSERT(op != NULL);
1237 ASSERT(!op->IsRegister()); 1240 ASSERT(!op->IsRegister());
1238 ASSERT(!op->IsDoubleRegister()); 1241 ASSERT(!op->IsDoubleRegister());
1239 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 1242 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
1240 if (NeedsEagerFrame()) { 1243 if (NeedsEagerFrame()) {
1241 return MemOperand(fp, StackSlotOffset(op->index())); 1244 int fp_offset = StackSlotOffset(op->index());
1245 if (op->index() >= 0) {
1246 // Loads and stores have a bigger reach in positive offset than negative.
1247 // When the load or the store can't be done in one instruction via fp
1248 // (too big negative offset), we try to access via jssp (positive offset).
1249 // We can reference a stack slot from jssp only if jssp references the end
1250 // of the stack slots. It's not the case when:
1251 // - stack_mode != kCanUseStackPointer: this is the case when a deferred
1252 // code saved the registers.
1253 // - after_push_argument_: arguments has been pushed for a call.
1254 // - inlined_arguments_: inlined arguments have been pushed once. All the
1255 // remainder of the function cannot trust jssp any longer.
1256 // - saves_caller_doubles: some double registers have been pushed, jssp
1257 // references the end of the double registers and not the end of the
1258 // stack slots.
1259 // Also, if the offset from fp is small enough to make a load/store in
1260 // one instruction, we use a fp access.
1261 if ((stack_mode == kCanUseStackPointer) && !after_push_argument_ &&
1262 !inlined_arguments_ && !is_int9(fp_offset) &&
1263 !info()->saves_caller_doubles()) {
1264 int jssp_offset =
1265 (GetStackSlotCount() - op->index() - 1) * kPointerSize;
1266 return MemOperand(masm()->StackPointer(), jssp_offset);
1267 }
1268 }
1269 return MemOperand(fp, fp_offset);
1242 } else { 1270 } else {
1243 // Retrieve parameter without eager stack-frame relative to the 1271 // Retrieve parameter without eager stack-frame relative to the
1244 // stack-pointer. 1272 // stack-pointer.
1245 return MemOperand(masm()->StackPointer(), 1273 return MemOperand(masm()->StackPointer(),
1246 ArgumentsOffsetWithoutFrame(op->index())); 1274 ArgumentsOffsetWithoutFrame(op->index()));
1247 } 1275 }
1248 } 1276 }
1249 1277
1250 1278
1251 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { 1279 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
1621 LPointerMap* pointers = instr->pointer_map(); 1649 LPointerMap* pointers = instr->pointer_map();
1622 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); 1650 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
1623 // The number of arguments is stored in argc (receiver) which is x0, as 1651 // The number of arguments is stored in argc (receiver) which is x0, as
1624 // expected by InvokeFunction. 1652 // expected by InvokeFunction.
1625 ParameterCount actual(argc); 1653 ParameterCount actual(argc);
1626 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); 1654 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator);
1627 } 1655 }
1628 1656
1629 1657
1630 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { 1658 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
1659 // We push some arguments and they will be pop in an other block. We can't
1660 // trust that jssp references the end of the stack slots until the end of
1661 // the function.
1662 inlined_arguments_ = true;
1631 Register result = ToRegister(instr->result()); 1663 Register result = ToRegister(instr->result());
1632 1664
1633 if (instr->hydrogen()->from_inlined()) { 1665 if (instr->hydrogen()->from_inlined()) {
1634 // When we are inside an inlined function, the arguments are the last things 1666 // When we are inside an inlined function, the arguments are the last things
1635 // that have been pushed on the stack. Therefore the arguments array can be 1667 // that have been pushed on the stack. Therefore the arguments array can be
1636 // accessed directly from jssp. 1668 // accessed directly from jssp.
1637 // However in the normal case, it is accessed via fp but there are two words 1669 // However in the normal case, it is accessed via fp but there are two words
1638 // on the stack between fp and the arguments (the saved lr and fp) and the 1670 // on the stack between fp and the arguments (the saved lr and fp) and the
1639 // LAccessArgumentsAt implementation take that into account. 1671 // LAccessArgumentsAt implementation take that into account.
1640 // In the inlined case we need to subtract the size of 2 words to jssp to 1672 // In the inlined case we need to subtract the size of 2 words to jssp to
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
1989 // this understanding is correct. 2021 // this understanding is correct.
1990 __ Call(code, RelocInfo::CODE_TARGET, TypeFeedbackId::None()); 2022 __ Call(code, RelocInfo::CODE_TARGET, TypeFeedbackId::None());
1991 } else { 2023 } else {
1992 ASSERT(instr->target()->IsRegister()); 2024 ASSERT(instr->target()->IsRegister());
1993 Register target = ToRegister(instr->target()); 2025 Register target = ToRegister(instr->target());
1994 generator.BeforeCall(__ CallSize(target)); 2026 generator.BeforeCall(__ CallSize(target));
1995 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); 2027 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag);
1996 __ Call(target); 2028 __ Call(target);
1997 } 2029 }
1998 generator.AfterCall(); 2030 generator.AfterCall();
2031 after_push_argument_ = false;
1999 } 2032 }
2000 2033
2001 2034
2002 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { 2035 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
2003 ASSERT(instr->IsMarkedAsCall()); 2036 ASSERT(instr->IsMarkedAsCall());
2004 ASSERT(ToRegister(instr->function()).is(x1)); 2037 ASSERT(ToRegister(instr->function()).is(x1));
2005 2038
2006 if (instr->hydrogen()->pass_argument_count()) { 2039 if (instr->hydrogen()->pass_argument_count()) {
2007 __ Mov(x0, Operand(instr->arity())); 2040 __ Mov(x0, Operand(instr->arity()));
2008 } 2041 }
2009 2042
2010 // Change context. 2043 // Change context.
2011 __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset)); 2044 __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset));
2012 2045
2013 // Load the code entry address 2046 // Load the code entry address
2014 __ Ldr(x10, FieldMemOperand(x1, JSFunction::kCodeEntryOffset)); 2047 __ Ldr(x10, FieldMemOperand(x1, JSFunction::kCodeEntryOffset));
2015 __ Call(x10); 2048 __ Call(x10);
2016 2049
2017 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 2050 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
2051 after_push_argument_ = false;
2018 } 2052 }
2019 2053
2020 2054
2021 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { 2055 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
2022 CallRuntime(instr->function(), instr->arity(), instr); 2056 CallRuntime(instr->function(), instr->arity(), instr);
2057 after_push_argument_ = false;
2023 } 2058 }
2024 2059
2025 2060
2026 void LCodeGen::DoCallStub(LCallStub* instr) { 2061 void LCodeGen::DoCallStub(LCallStub* instr) {
2027 ASSERT(ToRegister(instr->context()).is(cp)); 2062 ASSERT(ToRegister(instr->context()).is(cp));
2028 ASSERT(ToRegister(instr->result()).is(x0)); 2063 ASSERT(ToRegister(instr->result()).is(x0));
2029 switch (instr->hydrogen()->major_key()) { 2064 switch (instr->hydrogen()->major_key()) {
2030 case CodeStub::RegExpExec: { 2065 case CodeStub::RegExpExec: {
2031 RegExpExecStub stub(isolate()); 2066 RegExpExecStub stub(isolate());
2032 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 2067 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2033 break; 2068 break;
2034 } 2069 }
2035 case CodeStub::SubString: { 2070 case CodeStub::SubString: {
2036 SubStringStub stub(isolate()); 2071 SubStringStub stub(isolate());
2037 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 2072 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2038 break; 2073 break;
2039 } 2074 }
2040 case CodeStub::StringCompare: { 2075 case CodeStub::StringCompare: {
2041 StringCompareStub stub(isolate()); 2076 StringCompareStub stub(isolate());
2042 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 2077 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2043 break; 2078 break;
2044 } 2079 }
2045 default: 2080 default:
2046 UNREACHABLE(); 2081 UNREACHABLE();
2047 } 2082 }
2083 after_push_argument_ = false;
2048 } 2084 }
2049 2085
2050 2086
2051 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 2087 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
2052 GenerateOsrPrologue(); 2088 GenerateOsrPrologue();
2053 } 2089 }
2054 2090
2055 2091
2056 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 2092 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
2057 Register temp = ToRegister(instr->temp()); 2093 Register temp = ToRegister(instr->temp());
(...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after
3095 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); 3131 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3096 ParameterCount count(instr->arity()); 3132 ParameterCount count(instr->arity());
3097 __ InvokeFunction(x1, count, CALL_FUNCTION, generator); 3133 __ InvokeFunction(x1, count, CALL_FUNCTION, generator);
3098 } else { 3134 } else {
3099 CallKnownFunction(known_function, 3135 CallKnownFunction(known_function,
3100 instr->hydrogen()->formal_parameter_count(), 3136 instr->hydrogen()->formal_parameter_count(),
3101 instr->arity(), 3137 instr->arity(),
3102 instr, 3138 instr,
3103 x1); 3139 x1);
3104 } 3140 }
3141 after_push_argument_ = false;
3105 } 3142 }
3106 3143
3107 3144
3108 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 3145 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
3109 Register temp1 = ToRegister(instr->temp1()); 3146 Register temp1 = ToRegister(instr->temp1());
3110 Register temp2 = ToRegister(instr->temp2()); 3147 Register temp2 = ToRegister(instr->temp2());
3111 3148
3112 // Get the frame pointer for the calling frame. 3149 // Get the frame pointer for the calling frame.
3113 __ Ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 3150 __ Ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3114 3151
(...skipping 1453 matching lines...) Expand 10 before | Expand all | Expand 10 after
4568 // Nothing to do. 4605 // Nothing to do.
4569 } 4606 }
4570 4607
4571 4608
4572 void LCodeGen::DoPushArgument(LPushArgument* instr) { 4609 void LCodeGen::DoPushArgument(LPushArgument* instr) {
4573 LOperand* argument = instr->value(); 4610 LOperand* argument = instr->value();
4574 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { 4611 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
4575 Abort(kDoPushArgumentNotImplementedForDoubleType); 4612 Abort(kDoPushArgumentNotImplementedForDoubleType);
4576 } else { 4613 } else {
4577 __ Push(ToRegister(argument)); 4614 __ Push(ToRegister(argument));
4615 after_push_argument_ = true;
4578 } 4616 }
4579 } 4617 }
4580 4618
4581 4619
4582 void LCodeGen::DoReturn(LReturn* instr) { 4620 void LCodeGen::DoReturn(LReturn* instr) {
4583 if (FLAG_trace && info()->IsOptimizing()) { 4621 if (FLAG_trace && info()->IsOptimizing()) {
4584 // Push the return value on the stack as the parameter. 4622 // Push the return value on the stack as the parameter.
4585 // Runtime::TraceExit returns its parameter in x0. We're leaving the code 4623 // Runtime::TraceExit returns its parameter in x0. We're leaving the code
4586 // managed by the register allocator and tearing down the frame, it's 4624 // managed by the register allocator and tearing down the frame, it's
4587 // safe to write to the context register. 4625 // safe to write to the context register.
(...skipping 1288 matching lines...) Expand 10 before | Expand all | Expand 10 after
5876 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); 5914 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
5877 // Index is equal to negated out of object property index plus 1. 5915 // Index is equal to negated out of object property index plus 1.
5878 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); 5916 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2));
5879 __ Ldr(result, FieldMemOperand(result, 5917 __ Ldr(result, FieldMemOperand(result,
5880 FixedArray::kHeaderSize - kPointerSize)); 5918 FixedArray::kHeaderSize - kPointerSize));
5881 __ Bind(deferred->exit()); 5919 __ Bind(deferred->exit());
5882 __ Bind(&done); 5920 __ Bind(&done);
5883 } 5921 }
5884 5922
5885 } } // namespace v8::internal 5923 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm64/lithium-codegen-arm64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698