Commit 66e53dc0 authored by haitao.feng@intel.com's avatar haitao.feng@intel.com

Use StackArgumenstAccessor and kPCOnStackSize/kFPOnStackSize to compute stack...

Use StackArgumenstAccessor and kPCOnStackSize/kFPOnStackSize to compute stack address/operand for X64

R=danno@chromium.org

Review URL: https://codereview.chromium.org/22267005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17094 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent df37f916
......@@ -881,9 +881,9 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
// rbp[16] : function arguments
// rbp[24] : receiver
// rbp[32] : function
static const int kArgumentsOffset = 2 * kPointerSize;
static const int kReceiverOffset = 3 * kPointerSize;
static const int kFunctionOffset = 4 * kPointerSize;
static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
static const int kFunctionOffset = kReceiverOffset + kPointerSize;
__ push(Operand(rbp, kFunctionOffset));
__ push(Operand(rbp, kArgumentsOffset));
......
......@@ -1986,11 +1986,6 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
// The key is in rdx and the parameter count is in rax.
// The displacement is used for skipping the frame pointer on the
// stack. It is the offset of the last parameter (if any) relative
// to the frame pointer.
static const int kDisplacement = 1 * kPointerSize;
// Check that the key is a smi.
Label slow;
__ JumpIfNotSmi(rdx, &slow);
......@@ -2012,10 +2007,10 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
__ j(above_equal, &slow);
// Read the argument from the stack and return it.
SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2);
__ lea(rbx, Operand(rbp, index.reg, index.scale, 0));
index = masm->SmiToNegativeIndex(rdx, rdx, kPointerSizeLog2);
__ movq(rax, Operand(rbx, index.reg, index.scale, kDisplacement));
__ SmiSub(rax, rax, rdx);
__ SmiToInteger32(rax, rax);
StackArgumentsAccessor args(rbp, rax, ARGUMENTS_DONT_CONTAIN_RECEIVER);
__ movq(rax, args.GetArgumentOperand(0));
__ Ret();
// Arguments adaptor case: Check index against actual arguments
......@@ -2027,10 +2022,11 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
__ j(above_equal, &slow);
// Read the argument from the stack and return it.
index = masm->SmiToIndex(rax, rcx, kPointerSizeLog2);
__ lea(rbx, Operand(rbx, index.reg, index.scale, 0));
index = masm->SmiToNegativeIndex(rdx, rdx, kPointerSizeLog2);
__ movq(rax, Operand(rbx, index.reg, index.scale, kDisplacement));
__ SmiSub(rcx, rcx, rdx);
__ SmiToInteger32(rcx, rcx);
StackArgumentsAccessor adaptor_args(rbx, rcx,
ARGUMENTS_DONT_CONTAIN_RECEIVER);
__ movq(rax, adaptor_args.GetArgumentOperand(0));
__ Ret();
// Slow-case: Handle non-smi or out-of-bounds access to arguments
......@@ -2404,11 +2400,16 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// rsp[24] : subject string
// rsp[32] : JSRegExp object
static const int kLastMatchInfoOffset = 1 * kPointerSize;
static const int kPreviousIndexOffset = 2 * kPointerSize;
static const int kSubjectOffset = 3 * kPointerSize;
static const int kJSRegExpOffset = 4 * kPointerSize;
enum RegExpExecStubArgumentIndices {
JS_REG_EXP_OBJECT_ARGUMENT_INDEX,
SUBJECT_STRING_ARGUMENT_INDEX,
PREVIOUS_INDEX_ARGUMENT_INDEX,
LAST_MATCH_INFO_ARGUMENT_INDEX,
REG_EXP_EXEC_ARGUMENT_COUNT
};
StackArgumentsAccessor args(rsp, REG_EXP_EXEC_ARGUMENT_COUNT,
ARGUMENTS_DONT_CONTAIN_RECEIVER);
Label runtime;
// Ensure that a RegExp stack is allocated.
Isolate* isolate = masm->isolate();
......@@ -2421,7 +2422,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ j(zero, &runtime);
// Check that the first argument is a JSRegExp object.
__ movq(rax, Operand(rsp, kJSRegExpOffset));
__ movq(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX));
__ JumpIfSmi(rax, &runtime);
__ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister);
__ j(not_equal, &runtime);
......@@ -2454,7 +2455,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// Reset offset for possibly sliced string.
__ Set(r14, 0);
__ movq(rdi, Operand(rsp, kSubjectOffset));
__ movq(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
__ JumpIfSmi(rdi, &runtime);
__ movq(r15, rdi); // Make a copy of the original subject string.
__ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
......@@ -2556,7 +2557,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// We have to use r15 instead of rdi to load the length because rdi might
// have been only made to look like a sequential string when it actually
// is an external string.
__ movq(rbx, Operand(rsp, kPreviousIndexOffset));
__ movq(rbx, args.GetArgumentOperand(PREVIOUS_INDEX_ARGUMENT_INDEX));
__ JumpIfNotSmi(rbx, &runtime);
__ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset));
__ j(above_equal, &runtime);
......@@ -2676,11 +2677,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// For failure return null.
__ LoadRoot(rax, Heap::kNullValueRootIndex);
__ ret(4 * kPointerSize);
__ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize);
// Load RegExp data.
__ bind(&success);
__ movq(rax, Operand(rsp, kJSRegExpOffset));
__ movq(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX));
__ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset));
__ SmiToInteger32(rax,
FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset));
......@@ -2689,7 +2690,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// rdx: Number of capture registers
// Check that the fourth object is a JSArray object.
__ movq(r15, Operand(rsp, kLastMatchInfoOffset));
__ movq(r15, args.GetArgumentOperand(LAST_MATCH_INFO_ARGUMENT_INDEX));
__ JumpIfSmi(r15, &runtime);
__ CmpObjectType(r15, JS_ARRAY_TYPE, kScratchRegister);
__ j(not_equal, &runtime);
......@@ -2713,7 +2714,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset),
kScratchRegister);
// Store last subject and last input.
__ movq(rax, Operand(rsp, kSubjectOffset));
__ movq(rax, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
__ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax);
__ movq(rcx, rax);
__ RecordWriteField(rbx,
......@@ -2756,7 +2757,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// Return last match info.
__ movq(rax, r15);
__ ret(4 * kPointerSize);
__ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize);
__ bind(&exception);
// Result must now be exception. If there is no pending exception already a
......@@ -4835,13 +4836,18 @@ void SubStringStub::Generate(MacroAssembler* masm) {
// rsp[16] : from
// rsp[24] : string
const int kToOffset = 1 * kPointerSize;
const int kFromOffset = kToOffset + kPointerSize;
const int kStringOffset = kFromOffset + kPointerSize;
const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset;
enum SubStringStubArgumentIndices {
STRING_ARGUMENT_INDEX,
FROM_ARGUMENT_INDEX,
TO_ARGUMENT_INDEX,
SUB_STRING_ARGUMENT_COUNT
};
StackArgumentsAccessor args(rsp, SUB_STRING_ARGUMENT_COUNT,
ARGUMENTS_DONT_CONTAIN_RECEIVER);
// Make sure first argument is a string.
__ movq(rax, Operand(rsp, kStringOffset));
__ movq(rax, args.GetArgumentOperand(STRING_ARGUMENT_INDEX));
STATIC_ASSERT(kSmiTag == 0);
__ testl(rax, Immediate(kSmiTagMask));
__ j(zero, &runtime);
......@@ -4851,8 +4857,8 @@ void SubStringStub::Generate(MacroAssembler* masm) {
// rax: string
// rbx: instance type
// Calculate length of sub string using the smi values.
__ movq(rcx, Operand(rsp, kToOffset));
__ movq(rdx, Operand(rsp, kFromOffset));
__ movq(rcx, args.GetArgumentOperand(TO_ARGUMENT_INDEX));
__ movq(rdx, args.GetArgumentOperand(FROM_ARGUMENT_INDEX));
__ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime);
__ SmiSub(rcx, rcx, rdx); // Overflow doesn't happen.
......@@ -4865,7 +4871,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
// Return original string.
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->sub_string_native(), 1);
__ ret(kArgumentsSize);
__ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
__ bind(&not_original_string);
Label single_char;
......@@ -4948,7 +4954,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
__ movq(FieldOperand(rax, SlicedString::kParentOffset), rdi);
__ movq(FieldOperand(rax, SlicedString::kOffsetOffset), rdx);
__ IncrementCounter(counters->sub_string_native(), 1);
__ ret(kArgumentsSize);
__ ret(3 * kPointerSize);
__ bind(&copy_routine);
}
......@@ -5002,7 +5008,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true);
__ movq(rsi, r14); // Restore rsi.
__ IncrementCounter(counters->sub_string_native(), 1);
__ ret(kArgumentsSize);
__ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
__ bind(&two_byte_sequential);
// Allocate the result.
......@@ -5027,7 +5033,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false);
__ movq(rsi, r14); // Restore esi.
__ IncrementCounter(counters->sub_string_native(), 1);
__ ret(kArgumentsSize);
__ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
// Just jump to runtime to create the sub string.
__ bind(&runtime);
......@@ -5041,7 +5047,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
StringCharAtGenerator generator(
rax, rdx, rcx, rax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER);
generator.GenerateFast(masm);
__ ret(kArgumentsSize);
__ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
generator.SkipSlow(masm, &runtime);
}
......
......@@ -747,7 +747,6 @@ void Code::PatchPlatformCodeAge(Isolate* isolate,
Operand StackArgumentsAccessor::GetArgumentOperand(int index) {
ASSERT(index >= 0);
ASSERT(base_reg_.is(rsp) || base_reg_.is(rbp));
int receiver = (receiver_mode_ == ARGUMENTS_CONTAIN_RECEIVER) ? 1 : 0;
int displacement_to_last_argument = base_reg_.is(rsp) ?
kPCOnStackSize : kFPOnStackSize + kPCOnStackSize;
......
......@@ -156,7 +156,7 @@ class StackArgumentsAccessor BASE_EMBEDDED {
Operand GetArgumentOperand(int index);
Operand GetReceiverOperand() {
ASSERT(receiver_mode_ == ARGUMENTS_CONTAIN_RECEIVER);
return GetArgumentOperand(0);;
return GetArgumentOperand(0);
}
private:
......
......@@ -70,11 +70,11 @@ class ExitFrameConstants : public AllStatic {
static const int kSPOffset = -1 * kPointerSize;
static const int kCallerFPOffset = +0 * kPointerSize;
static const int kCallerPCOffset = +1 * kPointerSize;
static const int kCallerPCOffset = kFPOnStackSize;
// FP-relative displacement of the caller's SP. It points just
// below the saved PC.
static const int kCallerSPDisplacement = +2 * kPointerSize;
static const int kCallerSPDisplacement = kCallerPCOffset + kPCOnStackSize;
};
......@@ -82,7 +82,7 @@ class JavaScriptFrameConstants : public AllStatic {
public:
// FP-relative.
static const int kLocal0Offset = StandardFrameConstants::kExpressionsOffset;
static const int kLastParameterOffset = +2 * kPointerSize;
static const int kLastParameterOffset = kFPOnStackSize + kPCOnStackSize;
static const int kFunctionOffset = StandardFrameConstants::kMarkerOffset;
// Caller SP-relative.
......
......@@ -140,10 +140,9 @@ void FullCodeGenerator::Generate() {
Label ok;
__ testq(rcx, rcx);
__ j(zero, &ok, Label::kNear);
// +1 for return address.
int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
__ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
__ movq(Operand(rsp, receiver_offset), kScratchRegister);
__ movq(args.GetReceiverOperand(), kScratchRegister);
__ bind(&ok);
}
......@@ -678,7 +677,8 @@ MemOperand FullCodeGenerator::StackOperand(Variable* var) {
int offset = -var->index() * kPointerSize;
// Adjust by a (parameter or local) base offset.
if (var->IsParameter()) {
offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
offset += kFPOnStackSize + kPCOnStackSize +
(info_->scope()->num_parameters() - 1) * kPointerSize;
} else {
offset += JavaScriptFrameConstants::kLocal0Offset;
}
......@@ -2632,7 +2632,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
}
// Push the receiver of the enclosing function and do runtime call.
__ push(Operand(rbp, (2 + info_->scope()->num_parameters()) * kPointerSize));
StackArgumentsAccessor args(rbp, info_->scope()->num_parameters());
__ push(args.GetReceiverOperand());
// Push the language mode.
__ Push(Smi::FromInt(language_mode()));
......
......@@ -134,10 +134,9 @@ bool LCodeGen::GeneratePrologue() {
Label ok;
__ testq(rcx, rcx);
__ j(zero, &ok, Label::kNear);
// +1 for return address.
int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize;
StackArgumentsAccessor args(rsp, scope()->num_parameters());
__ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
__ movq(Operand(rsp, receiver_offset), kScratchRegister);
__ movq(args.GetReceiverOperand(), kScratchRegister);
__ bind(&ok);
}
}
......@@ -2828,8 +2827,9 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
instr->index()->IsConstantOperand()) {
int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index()));
int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length()));
int index = (const_length - const_index) + 1;
__ movq(result, Operand(arguments, index * kPointerSize));
StackArgumentsAccessor args(arguments, const_length,
ARGUMENTS_DONT_CONTAIN_RECEIVER);
__ movq(result, args.GetArgumentOperand(const_index));
} else {
Register length = ToRegister(instr->length());
// There are two words between the frame pointer and the last argument.
......@@ -2839,8 +2839,9 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
} else {
__ subl(length, ToOperand(instr->index()));
}
__ movq(result,
Operand(arguments, length, times_pointer_size, kPointerSize));
StackArgumentsAccessor args(arguments, length,
ARGUMENTS_DONT_CONTAIN_RECEIVER);
__ movq(result, args.GetArgumentOperand(0));
}
}
......@@ -3044,7 +3045,7 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
Register result = ToRegister(instr->result());
if (instr->hydrogen()->from_inlined()) {
__ lea(result, Operand(rsp, -2 * kPointerSize));
__ lea(result, Operand(rsp, -kFPOnStackSize + -kPCOnStackSize));
} else {
// Check for arguments adapter frame.
Label done, adapted;
......@@ -3166,7 +3167,9 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
__ testl(length, length);
__ j(zero, &invoke, Label::kNear);
__ bind(&loop);
__ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
StackArgumentsAccessor args(elements, length,
ARGUMENTS_DONT_CONTAIN_RECEIVER);
__ push(args.GetArgumentOperand(0));
__ decl(length);
__ j(not_zero, &loop);
......
......@@ -2765,7 +2765,8 @@ Operand MacroAssembler::SafepointRegisterSlot(Register reg) {
void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
int handler_index) {
// Adjust this code if not the case.
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize +
kFPOnStackSize);
STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
......@@ -2824,7 +2825,8 @@ void MacroAssembler::JumpToHandlerEntry() {
void MacroAssembler::Throw(Register value) {
// Adjust this code if not the case.
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize +
kFPOnStackSize);
STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
......@@ -2864,7 +2866,8 @@ void MacroAssembler::Throw(Register value) {
void MacroAssembler::ThrowUncatchable(Register value) {
// Adjust this code if not the case.
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize +
kFPOnStackSize);
STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
......@@ -3704,9 +3707,10 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
void MacroAssembler::EnterExitFramePrologue(bool save_rax) {
// Set up the frame structure on the stack.
// All constants are relative to the frame pointer of the exit frame.
ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
ASSERT(ExitFrameConstants::kCallerSPDisplacement ==
kFPOnStackSize + kPCOnStackSize);
ASSERT(ExitFrameConstants::kCallerPCOffset == kFPOnStackSize);
ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
push(rbp);
movq(rbp, rsp);
......
......@@ -2198,7 +2198,7 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ movq(rdx, args.GetArgumentOperand(argc - 1));
__ movq(rdx, args.GetReceiverOperand());
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
name, &miss);
......@@ -2211,7 +2211,7 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
// Load the char code argument.
Register code = rbx;
__ movq(code, args.GetArgumentOperand(argc));
__ movq(code, args.GetArgumentOperand(1));
// Check the code is a smi.
Label slow;
......@@ -2261,6 +2261,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
// -- rsp[(argc + 1) * 4] : receiver
// -----------------------------------
const int argc = arguments().immediate();
StackArgumentsAccessor args(rsp, argc);
// If the object is not a JSObject or we got an unexpected number of
// arguments, bail out to the regular call.
......@@ -2272,7 +2273,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ movq(rdx, Operand(rsp, 2 * kPointerSize));
__ movq(rdx, args.GetReceiverOperand());
STATIC_ASSERT(kSmiTag == 0);
__ JumpIfSmi(rdx, &miss);
......@@ -2287,7 +2288,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
}
// Load the (only) argument into rax.
__ movq(rax, Operand(rsp, 1 * kPointerSize));
__ movq(rax, args.GetArgumentOperand(1));
// Check if the argument is a smi.
Label smi;
......@@ -2354,7 +2355,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
// Return the argument (when it's an already round heap number).
__ bind(&already_round);
__ movq(rax, Operand(rsp, 1 * kPointerSize));
__ movq(rax, args.GetArgumentOperand(1));
__ ret(2 * kPointerSize);
// Tail call the full function. We do not have to patch the receiver
......@@ -2398,7 +2399,7 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ movq(rdx, args.GetArgumentOperand(argc - 1));
__ movq(rdx, args.GetReceiverOperand());
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
name, &miss);
......@@ -2409,7 +2410,7 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
GenerateLoadFunctionFromCell(cell, function, &miss);
}
// Load the (only) argument into rax.
__ movq(rax, args.GetArgumentOperand(argc));
__ movq(rax, args.GetArgumentOperand(1));
// Check if the argument is a smi.
Label not_smi;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment