Commit 62e02829 authored by Alexander.Gilday2's avatar Alexander.Gilday2 Committed by Commit bot

[builtins] Migrate DatePrototype_GetField to TurboFan builtin.

Migrate the platform DatePrototype_GetField (and all wrappers) to
TurboFan.

BUG=v8:5049

Review-Url: https://codereview.chromium.org/2263533002
Cr-Commit-Position: refs/heads/master@{#39438}
parent e16f83c7
......@@ -1866,71 +1866,6 @@ void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
Generate_OnStackReplacementHelper(masm, true);
}
// static
void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index) {
// ----------- S t a t e -------------
// -- r0 : number of arguments
// -- r1 : function
// -- cp : context
// -- lr : return address
// -- sp[0] : receiver
// -----------------------------------
// 1. Pop receiver into r0 and check that it's actually a JSDate object.
Label receiver_not_date;
{
__ Pop(r0);
__ JumpIfSmi(r0, &receiver_not_date);
__ CompareObjectType(r0, r2, r3, JS_DATE_TYPE);
__ b(ne, &receiver_not_date);
}
// 2. Load the specified date field, falling back to the runtime as necessary.
if (field_index == JSDate::kDateValue) {
__ ldr(r0, FieldMemOperand(r0, JSDate::kValueOffset));
} else {
if (field_index < JSDate::kFirstUncachedField) {
Label stamp_mismatch;
__ mov(r1, Operand(ExternalReference::date_cache_stamp(masm->isolate())));
__ ldr(r1, MemOperand(r1));
__ ldr(ip, FieldMemOperand(r0, JSDate::kCacheStampOffset));
__ cmp(r1, ip);
__ b(ne, &stamp_mismatch);
__ ldr(r0, FieldMemOperand(
r0, JSDate::kValueOffset + field_index * kPointerSize));
__ Ret();
__ bind(&stamp_mismatch);
}
FrameScope scope(masm, StackFrame::INTERNAL);
__ PrepareCallCFunction(2, r1);
__ mov(r1, Operand(Smi::FromInt(field_index)));
__ CallCFunction(
ExternalReference::get_date_field_function(masm->isolate()), 2);
}
__ Ret();
// 3. Raise a TypeError if the receiver is not a date.
__ bind(&receiver_not_date);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Push(r0);
__ Move(r0, Smi::FromInt(0));
__ EnterBuiltinFrame(cp, r1, r0);
__ CallRuntime(Runtime::kThrowNotDateError);
// It's far from obvious, but this final trailing instruction after the call
// is required for StackFrame::LookupCode to work correctly. To illustrate
// why: if call were the final instruction in the code object, then the pc
// (== return address) would point beyond the code object when the stack is
// traversed. When we then try to look up the code object through
// StackFrame::LookupCode, we actually return the next code object that
// happens to be on the same page in memory.
// TODO(jgruber): A proper fix for this would be nice.
__ nop();
}
}
// static
void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -1863,70 +1863,6 @@ void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
Generate_OnStackReplacementHelper(masm, true);
}
// static
void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index) {
// ----------- S t a t e -------------
// -- x0 : number of arguments
// -- x1 : function
// -- cp : context
// -- lr : return address
// -- jssp[0] : receiver
// -----------------------------------
ASM_LOCATION("Builtins::Generate_DatePrototype_GetField");
// 1. Pop receiver into x0 and check that it's actually a JSDate object.
Label receiver_not_date;
{
__ Pop(x0);
__ JumpIfSmi(x0, &receiver_not_date);
__ JumpIfNotObjectType(x0, x2, x3, JS_DATE_TYPE, &receiver_not_date);
}
// 2. Load the specified date field, falling back to the runtime as necessary.
if (field_index == JSDate::kDateValue) {
__ Ldr(x0, FieldMemOperand(x0, JSDate::kValueOffset));
} else {
if (field_index < JSDate::kFirstUncachedField) {
Label stamp_mismatch;
__ Mov(x1, ExternalReference::date_cache_stamp(masm->isolate()));
__ Ldr(x1, MemOperand(x1));
__ Ldr(x2, FieldMemOperand(x0, JSDate::kCacheStampOffset));
__ Cmp(x1, x2);
__ B(ne, &stamp_mismatch);
__ Ldr(x0, FieldMemOperand(
x0, JSDate::kValueOffset + field_index * kPointerSize));
__ Ret();
__ Bind(&stamp_mismatch);
}
FrameScope scope(masm, StackFrame::INTERNAL);
__ Mov(x1, Smi::FromInt(field_index));
__ CallCFunction(
ExternalReference::get_date_field_function(masm->isolate()), 2);
}
__ Ret();
// 3. Raise a TypeError if the receiver is not a date.
__ Bind(&receiver_not_date);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Push(x0);
__ Mov(x0, Smi::FromInt(0));
__ EnterBuiltinFrame(cp, x1, x0);
__ CallRuntime(Runtime::kThrowNotDateError);
// It's far from obvious, but this final trailing instruction after the call
// is required for StackFrame::LookupCode to work correctly. To illustrate
// why: if call were the final instruction in the code object, then the pc
// (== return address) would point beyond the code object when the stack is
// traversed. When we then try to look up the code object through
// StackFrame::LookupCode, we actually return the next code object that
// happens to be on the same page in memory.
// TODO(jgruber): A proper fix for this would be nice.
__ nop();
}
}
// static
void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -909,93 +909,156 @@ BUILTIN(DatePrototypeToJson) {
}
// static
void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kDay);
void Builtins::Generate_DatePrototype_GetField(CodeStubAssembler* assembler,
int field_index) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
Node* receiver = assembler->Parameter(0);
Node* context = assembler->Parameter(3);
Label receiver_not_date(assembler, Label::kDeferred);
assembler->GotoIf(assembler->WordIsSmi(receiver), &receiver_not_date);
Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
assembler->GotoIf(
assembler->Word32NotEqual(receiver_instance_type,
assembler->Int32Constant(JS_DATE_TYPE)),
&receiver_not_date);
// Load the specified date field, falling back to the runtime as necessary.
if (field_index == JSDate::kDateValue) {
assembler->Return(
assembler->LoadObjectField(receiver, JSDate::kValueOffset));
} else {
if (field_index < JSDate::kFirstUncachedField) {
Label stamp_mismatch(assembler, Label::kDeferred);
Node* date_cache_stamp = assembler->Load(
MachineType::AnyTagged(),
assembler->ExternalConstant(
ExternalReference::date_cache_stamp(assembler->isolate())));
Node* cache_stamp =
assembler->LoadObjectField(receiver, JSDate::kCacheStampOffset);
assembler->GotoIf(assembler->WordNotEqual(date_cache_stamp, cache_stamp),
&stamp_mismatch);
assembler->Return(assembler->LoadObjectField(
receiver, JSDate::kValueOffset + field_index * kPointerSize));
assembler->Bind(&stamp_mismatch);
}
Node* field_index_smi = assembler->SmiConstant(Smi::FromInt(field_index));
Node* function = assembler->ExternalConstant(
ExternalReference::get_date_field_function(assembler->isolate()));
Node* result = assembler->CallCFunction2(
MachineType::AnyTagged(), MachineType::Pointer(),
MachineType::AnyTagged(), function, receiver, field_index_smi);
assembler->Return(result);
}
// Raise a TypeError if the receiver is not a date.
assembler->Bind(&receiver_not_date);
{
Node* result = assembler->CallRuntime(Runtime::kThrowNotDateError, context);
assembler->Return(result);
}
}
// static
void Builtins::Generate_DatePrototypeGetDate(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kDay);
}
// static
void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kWeekday);
void Builtins::Generate_DatePrototypeGetDay(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kWeekday);
}
// static
void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kYear);
void Builtins::Generate_DatePrototypeGetFullYear(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kYear);
}
// static
void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kHour);
void Builtins::Generate_DatePrototypeGetHours(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kHour);
}
// static
void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kMillisecond);
void Builtins::Generate_DatePrototypeGetMilliseconds(
CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kMillisecond);
}
// static
void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kMinute);
void Builtins::Generate_DatePrototypeGetMinutes(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kMinute);
}
// static
void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kMonth);
void Builtins::Generate_DatePrototypeGetMonth(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kMonth);
}
// static
void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kSecond);
void Builtins::Generate_DatePrototypeGetSeconds(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kSecond);
}
// static
void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kDateValue);
void Builtins::Generate_DatePrototypeGetTime(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kDateValue);
}
// static
void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset);
void Builtins::Generate_DatePrototypeGetTimezoneOffset(
CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kTimezoneOffset);
}
// static
void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kDayUTC);
void Builtins::Generate_DatePrototypeGetUTCDate(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kDayUTC);
}
// static
void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC);
void Builtins::Generate_DatePrototypeGetUTCDay(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kWeekdayUTC);
}
// static
void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kYearUTC);
void Builtins::Generate_DatePrototypeGetUTCFullYear(
CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kYearUTC);
}
// static
void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kHourUTC);
void Builtins::Generate_DatePrototypeGetUTCHours(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kHourUTC);
}
// static
void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC);
void Builtins::Generate_DatePrototypeGetUTCMilliseconds(
CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kMillisecondUTC);
}
// static
void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC);
void Builtins::Generate_DatePrototypeGetUTCMinutes(
CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kMinuteUTC);
}
// static
void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC);
void Builtins::Generate_DatePrototypeGetUTCMonth(CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kMonthUTC);
}
// static
void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) {
Generate_DatePrototype_GetField(masm, JSDate::kSecondUTC);
void Builtins::Generate_DatePrototypeGetUTCSeconds(
CodeStubAssembler* assembler) {
Generate_DatePrototype_GetField(assembler, JSDate::kSecondUTC);
}
} // namespace internal
......
......@@ -270,41 +270,41 @@ namespace internal {
CPP(DateConstructor) \
CPP(DateConstructor_ConstructStub) \
/* ES6 section 20.3.4.2 Date.prototype.getDate ( ) */ \
ASM(DatePrototypeGetDate) \
TFJ(DatePrototypeGetDate, 1) \
/* ES6 section 20.3.4.3 Date.prototype.getDay ( ) */ \
ASM(DatePrototypeGetDay) \
TFJ(DatePrototypeGetDay, 1) \
/* ES6 section 20.3.4.4 Date.prototype.getFullYear ( ) */ \
ASM(DatePrototypeGetFullYear) \
TFJ(DatePrototypeGetFullYear, 1) \
/* ES6 section 20.3.4.5 Date.prototype.getHours ( ) */ \
ASM(DatePrototypeGetHours) \
TFJ(DatePrototypeGetHours, 1) \
/* ES6 section 20.3.4.6 Date.prototype.getMilliseconds ( ) */ \
ASM(DatePrototypeGetMilliseconds) \
TFJ(DatePrototypeGetMilliseconds, 1) \
/* ES6 section 20.3.4.7 Date.prototype.getMinutes ( ) */ \
ASM(DatePrototypeGetMinutes) \
TFJ(DatePrototypeGetMinutes, 1) \
/* ES6 section 20.3.4.8 Date.prototype.getMonth */ \
ASM(DatePrototypeGetMonth) \
TFJ(DatePrototypeGetMonth, 1) \
/* ES6 section 20.3.4.9 Date.prototype.getSeconds ( ) */ \
ASM(DatePrototypeGetSeconds) \
TFJ(DatePrototypeGetSeconds, 1) \
/* ES6 section 20.3.4.10 Date.prototype.getTime ( ) */ \
ASM(DatePrototypeGetTime) \
TFJ(DatePrototypeGetTime, 1) \
/* ES6 section 20.3.4.11 Date.prototype.getTimezoneOffset ( ) */ \
ASM(DatePrototypeGetTimezoneOffset) \
TFJ(DatePrototypeGetTimezoneOffset, 1) \
/* ES6 section 20.3.4.12 Date.prototype.getUTCDate ( ) */ \
ASM(DatePrototypeGetUTCDate) \
TFJ(DatePrototypeGetUTCDate, 1) \
/* ES6 section 20.3.4.13 Date.prototype.getUTCDay ( ) */ \
ASM(DatePrototypeGetUTCDay) \
TFJ(DatePrototypeGetUTCDay, 1) \
/* ES6 section 20.3.4.14 Date.prototype.getUTCFullYear ( ) */ \
ASM(DatePrototypeGetUTCFullYear) \
TFJ(DatePrototypeGetUTCFullYear, 1) \
/* ES6 section 20.3.4.15 Date.prototype.getUTCHours ( ) */ \
ASM(DatePrototypeGetUTCHours) \
TFJ(DatePrototypeGetUTCHours, 1) \
/* ES6 section 20.3.4.16 Date.prototype.getUTCMilliseconds ( ) */ \
ASM(DatePrototypeGetUTCMilliseconds) \
TFJ(DatePrototypeGetUTCMilliseconds, 1) \
/* ES6 section 20.3.4.17 Date.prototype.getUTCMinutes ( ) */ \
ASM(DatePrototypeGetUTCMinutes) \
TFJ(DatePrototypeGetUTCMinutes, 1) \
/* ES6 section 20.3.4.18 Date.prototype.getUTCMonth ( ) */ \
ASM(DatePrototypeGetUTCMonth) \
TFJ(DatePrototypeGetUTCMonth, 1) \
/* ES6 section 20.3.4.19 Date.prototype.getUTCSeconds ( ) */ \
ASM(DatePrototypeGetUTCSeconds) \
TFJ(DatePrototypeGetUTCSeconds, 1) \
CPP(DatePrototypeGetYear) \
CPP(DatePrototypeSetYear) \
CPP(DateNow) \
......@@ -682,7 +682,7 @@ class Builtins {
static void Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, CallableType function_type);
static void Generate_DatePrototype_GetField(MacroAssembler* masm,
static void Generate_DatePrototype_GetField(CodeStubAssembler* masm,
int field_index);
enum class MathMaxMinKind { kMax, kMin };
......
......@@ -1359,71 +1359,6 @@ void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
}
// static
void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index) {
// ----------- S t a t e -------------
// -- eax : number of arguments
// -- edi : function
// -- esi : context
// -- esp[0] : return address
// -- esp[4] : receiver
// -----------------------------------
// 1. Load receiver into eax and check that it's actually a JSDate object.
Label receiver_not_date;
{
__ mov(eax, Operand(esp, kPointerSize));
__ JumpIfSmi(eax, &receiver_not_date);
__ CmpObjectType(eax, JS_DATE_TYPE, ebx);
__ j(not_equal, &receiver_not_date);
}
// 2. Load the specified date field, falling back to the runtime as necessary.
if (field_index == JSDate::kDateValue) {
__ mov(eax, FieldOperand(eax, JSDate::kValueOffset));
} else {
if (field_index < JSDate::kFirstUncachedField) {
Label stamp_mismatch;
__ mov(edx, Operand::StaticVariable(
ExternalReference::date_cache_stamp(masm->isolate())));
__ cmp(edx, FieldOperand(eax, JSDate::kCacheStampOffset));
__ j(not_equal, &stamp_mismatch, Label::kNear);
__ mov(eax, FieldOperand(
eax, JSDate::kValueOffset + field_index * kPointerSize));
__ ret(1 * kPointerSize);
__ bind(&stamp_mismatch);
}
FrameScope scope(masm, StackFrame::INTERNAL);
__ PrepareCallCFunction(2, ebx);
__ mov(Operand(esp, 0), eax);
__ mov(Operand(esp, 1 * kPointerSize),
Immediate(Smi::FromInt(field_index)));
__ CallCFunction(
ExternalReference::get_date_field_function(masm->isolate()), 2);
}
__ ret(1 * kPointerSize);
// 3. Raise a TypeError if the receiver is not a date.
__ bind(&receiver_not_date);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Move(ebx, Immediate(0));
__ EnterBuiltinFrame(esi, edi, ebx);
__ CallRuntime(Runtime::kThrowNotDateError);
// It's far from obvious, but this final trailing instruction after the call
// is required for StackFrame::LookupCode to work correctly. To illustrate
// why: if call were the final instruction in the code object, then the pc
// (== return address) would point beyond the code object when the stack is
// traversed. When we then try to look up the code object through
// StackFrame::LookupCode, we actually return the next code object that
// happens to be on the same page in memory.
// TODO(jgruber): A proper fix for this would be nice.
__ nop();
}
}
// static
void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -1852,71 +1852,6 @@ void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
Generate_OnStackReplacementHelper(masm, true);
}
// static
void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : function
// -- cp : context
// -- sp[0] : receiver
// -----------------------------------
// 1. Pop receiver into a0 and check that it's actually a JSDate object.
Label receiver_not_date;
{
__ Pop(a0);
__ JumpIfSmi(a0, &receiver_not_date);
__ GetObjectType(a0, t0, t0);
__ Branch(&receiver_not_date, ne, t0, Operand(JS_DATE_TYPE));
}
// 2. Load the specified date field, falling back to the runtime as necessary.
if (field_index == JSDate::kDateValue) {
__ Ret(USE_DELAY_SLOT);
__ lw(v0, FieldMemOperand(a0, JSDate::kValueOffset)); // In delay slot.
} else {
if (field_index < JSDate::kFirstUncachedField) {
Label stamp_mismatch;
__ li(a1, Operand(ExternalReference::date_cache_stamp(masm->isolate())));
__ lw(a1, MemOperand(a1));
__ lw(t0, FieldMemOperand(a0, JSDate::kCacheStampOffset));
__ Branch(&stamp_mismatch, ne, t0, Operand(a1));
__ Ret(USE_DELAY_SLOT);
__ lw(v0, FieldMemOperand(
a0, JSDate::kValueOffset +
field_index * kPointerSize)); // In delay slot.
__ bind(&stamp_mismatch);
}
FrameScope scope(masm, StackFrame::INTERNAL);
__ PrepareCallCFunction(2, t0);
__ li(a1, Operand(Smi::FromInt(field_index)));
__ CallCFunction(
ExternalReference::get_date_field_function(masm->isolate()), 2);
}
__ Ret();
// 3. Raise a TypeError if the receiver is not a date.
__ bind(&receiver_not_date);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Push(a0);
__ Move(a0, Smi::FromInt(0));
__ EnterBuiltinFrame(cp, a1, a0);
__ CallRuntime(Runtime::kThrowNotDateError);
// It's far from obvious, but this final trailing instruction after the call
// is required for StackFrame::LookupCode to work correctly. To illustrate
// why: if call were the final instruction in the code object, then the pc
// (== return address) would point beyond the code object when the stack is
// traversed. When we then try to look up the code object through
// StackFrame::LookupCode, we actually return the next code object that
// happens to be on the same page in memory.
// TODO(jgruber): A proper fix for this would be nice.
__ nop();
}
}
// static
void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -1846,71 +1846,6 @@ void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
Generate_OnStackReplacementHelper(masm, true);
}
// static
void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : function
// -- cp : context
// -- sp[0] : receiver
// -----------------------------------
// 1. Pop receiver into a0 and check that it's actually a JSDate object.
Label receiver_not_date;
{
__ Pop(a0);
__ JumpIfSmi(a0, &receiver_not_date);
__ GetObjectType(a0, t0, t0);
__ Branch(&receiver_not_date, ne, t0, Operand(JS_DATE_TYPE));
}
// 2. Load the specified date field, falling back to the runtime as necessary.
if (field_index == JSDate::kDateValue) {
__ Ret(USE_DELAY_SLOT);
__ ld(v0, FieldMemOperand(a0, JSDate::kValueOffset)); // In delay slot.
} else {
if (field_index < JSDate::kFirstUncachedField) {
Label stamp_mismatch;
__ li(a1, Operand(ExternalReference::date_cache_stamp(masm->isolate())));
__ ld(a1, MemOperand(a1));
__ ld(t0, FieldMemOperand(a0, JSDate::kCacheStampOffset));
__ Branch(&stamp_mismatch, ne, t0, Operand(a1));
__ Ret(USE_DELAY_SLOT);
__ ld(v0, FieldMemOperand(
a0, JSDate::kValueOffset +
field_index * kPointerSize)); // In delay slot.
__ bind(&stamp_mismatch);
}
FrameScope scope(masm, StackFrame::INTERNAL);
__ PrepareCallCFunction(2, t0);
__ li(a1, Operand(Smi::FromInt(field_index)));
__ CallCFunction(
ExternalReference::get_date_field_function(masm->isolate()), 2);
}
__ Ret();
// 3. Raise a TypeError if the receiver is not a date.
__ bind(&receiver_not_date);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Push(a0);
__ Move(a0, Smi::FromInt(0));
__ EnterBuiltinFrame(cp, a1, a0);
__ CallRuntime(Runtime::kThrowNotDateError);
// It's far from obvious, but this final trailing instruction after the call
// is required for StackFrame::LookupCode to work correctly. To illustrate
// why: if call were the final instruction in the code object, then the pc
// (== return address) would point beyond the code object when the stack is
// traversed. When we then try to look up the code object through
// StackFrame::LookupCode, we actually return the next code object that
// happens to be on the same page in memory.
// TODO(jgruber): A proper fix for this would be nice.
__ nop();
}
}
// static
void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -1885,71 +1885,6 @@ void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
Generate_OnStackReplacementHelper(masm, true);
}
// static
void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index) {
// ----------- S t a t e -------------
// -- r3 : number of arguments
// -- r4 : function
// -- cp : context
// -- lr : return address
// -- sp[0] : receiver
// -----------------------------------
// 1. Pop receiver into r3 and check that it's actually a JSDate object.
Label receiver_not_date;
{
__ Pop(r3);
__ JumpIfSmi(r3, &receiver_not_date);
__ CompareObjectType(r3, r5, r6, JS_DATE_TYPE);
__ bne(&receiver_not_date);
}
// 2. Load the specified date field, falling back to the runtime as necessary.
if (field_index == JSDate::kDateValue) {
__ LoadP(r3, FieldMemOperand(r3, JSDate::kValueOffset));
} else {
if (field_index < JSDate::kFirstUncachedField) {
Label stamp_mismatch;
__ mov(r4, Operand(ExternalReference::date_cache_stamp(masm->isolate())));
__ LoadP(r4, MemOperand(r4));
__ LoadP(ip, FieldMemOperand(r3, JSDate::kCacheStampOffset));
__ cmp(r4, ip);
__ bne(&stamp_mismatch);
__ LoadP(r3, FieldMemOperand(
r3, JSDate::kValueOffset + field_index * kPointerSize));
__ Ret();
__ bind(&stamp_mismatch);
}
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ PrepareCallCFunction(2, r4);
__ LoadSmiLiteral(r4, Smi::FromInt(field_index));
__ CallCFunction(
ExternalReference::get_date_field_function(masm->isolate()), 2);
}
__ Ret();
// 3. Raise a TypeError if the receiver is not a date.
__ bind(&receiver_not_date);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ push(r3);
__ LoadSmiLiteral(r3, Smi::FromInt(0));
__ EnterBuiltinFrame(cp, r4, r3);
__ CallRuntime(Runtime::kThrowNotDateError);
// It's far from obvious, but this final trailing instruction after the call
// is required for StackFrame::LookupCode to work correctly. To illustrate
// why: if call were the final instruction in the code object, then the pc
// (== return address) would point beyond the code object when the stack is
// traversed. When we then try to look up the code object through
// StackFrame::LookupCode, we actually return the next code object that
// happens to be on the same page in memory.
// TODO(jgruber): A proper fix for this would be nice.
__ nop();
}
}
// static
void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -1885,72 +1885,6 @@ void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
Generate_OnStackReplacementHelper(masm, true);
}
// static
void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index) {
// ----------- S t a t e -------------
// -- r2 : number of arguments
// -- r3 : function
// -- cp : context
// -- lr : return address
// -- sp[0] : receiver
// -----------------------------------
// 1. Pop receiver into r2 and check that it's actually a JSDate object.
Label receiver_not_date;
{
__ Pop(r2);
__ JumpIfSmi(r2, &receiver_not_date);
__ CompareObjectType(r2, r4, r5, JS_DATE_TYPE);
__ bne(&receiver_not_date);
}
// 2. Load the specified date field, falling back to the runtime as necessary.
if (field_index == JSDate::kDateValue) {
__ LoadP(r2, FieldMemOperand(r2, JSDate::kValueOffset));
} else {
if (field_index < JSDate::kFirstUncachedField) {
Label stamp_mismatch;
__ mov(r3, Operand(ExternalReference::date_cache_stamp(masm->isolate())));
__ LoadP(r3, MemOperand(r3));
__ LoadP(ip, FieldMemOperand(r2, JSDate::kCacheStampOffset));
__ CmpP(r3, ip);
__ bne(&stamp_mismatch);
__ LoadP(r2, FieldMemOperand(
r2, JSDate::kValueOffset + field_index * kPointerSize));
__ Ret();
__ bind(&stamp_mismatch);
}
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ PrepareCallCFunction(2, r3);
__ LoadSmiLiteral(r3, Smi::FromInt(field_index));
__ CallCFunction(
ExternalReference::get_date_field_function(masm->isolate()), 2);
}
__ Ret();
// 3. Raise a TypeError if the receiver is not a date.
__ bind(&receiver_not_date);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ push(r2);
__ LoadSmiLiteral(r2, Smi::FromInt(0));
__ EnterBuiltinFrame(cp, r3, r2);
__ CallRuntime(Runtime::kThrowNotDateError);
// It's far from obvious, but this final trailing instruction after the call
// is required for StackFrame::LookupCode to work correctly. To illustrate
// why: if call were the final instruction in the code object, then the pc
// (== return address) would point beyond the code object when the stack is
// traversed. When we then try to look up the code object through
// StackFrame::LookupCode, we actually return the next code object that
// happens to be on the same page in memory.
// TODO(jgruber): A proper fix for this would be nice.
__ nop();
}
}
// static
void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -1329,70 +1329,6 @@ void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
}
// static
void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index) {
// ----------- S t a t e -------------
// -- rax : number of arguments
// -- rdi : function
// -- rsi : context
// -- rsp[0] : return address
// -- rsp[8] : receiver
// -----------------------------------
// 1. Load receiver into rax and check that it's actually a JSDate object.
Label receiver_not_date;
{
StackArgumentsAccessor args(rsp, 0);
__ movp(rax, args.GetReceiverOperand());
__ JumpIfSmi(rax, &receiver_not_date);
__ CmpObjectType(rax, JS_DATE_TYPE, rbx);
__ j(not_equal, &receiver_not_date);
}
// 2. Load the specified date field, falling back to the runtime as necessary.
if (field_index == JSDate::kDateValue) {
__ movp(rax, FieldOperand(rax, JSDate::kValueOffset));
} else {
if (field_index < JSDate::kFirstUncachedField) {
Label stamp_mismatch;
__ Load(rdx, ExternalReference::date_cache_stamp(masm->isolate()));
__ cmpp(rdx, FieldOperand(rax, JSDate::kCacheStampOffset));
__ j(not_equal, &stamp_mismatch, Label::kNear);
__ movp(rax, FieldOperand(
rax, JSDate::kValueOffset + field_index * kPointerSize));
__ ret(1 * kPointerSize);
__ bind(&stamp_mismatch);
}
FrameScope scope(masm, StackFrame::INTERNAL);
__ PrepareCallCFunction(2);
__ Move(arg_reg_1, rax);
__ Move(arg_reg_2, Smi::FromInt(field_index));
__ CallCFunction(
ExternalReference::get_date_field_function(masm->isolate()), 2);
}
__ ret(1 * kPointerSize);
// 3. Raise a TypeError if the receiver is not a date.
__ bind(&receiver_not_date);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Move(rbx, Smi::FromInt(0));
__ EnterBuiltinFrame(rsi, rdi, rbx);
__ CallRuntime(Runtime::kThrowNotDateError);
// It's far from obvious, but this final trailing instruction after the call
// is required for StackFrame::LookupCode to work correctly. To illustrate
// why: if call were the final instruction in the code object, then the pc
// (== return address) would point beyond the code object when the stack is
// traversed. When we then try to look up the code object through
// StackFrame::LookupCode, we actually return the next code object that
// happens to be on the same page in memory.
// TODO(jgruber): A proper fix for this would be nice.
__ int3();
}
}
// static
void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -1353,71 +1353,6 @@ void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
}
// static
void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index) {
// ----------- S t a t e -------------
// -- eax : number of arguments
// -- edi : function
// -- esi : context
// -- esp[0] : return address
// -- esp[4] : receiver
// -----------------------------------
// 1. Load receiver into eax and check that it's actually a JSDate object.
Label receiver_not_date;
{
__ mov(eax, Operand(esp, kPointerSize));
__ JumpIfSmi(eax, &receiver_not_date);
__ CmpObjectType(eax, JS_DATE_TYPE, ebx);
__ j(not_equal, &receiver_not_date);
}
// 2. Load the specified date field, falling back to the runtime as necessary.
if (field_index == JSDate::kDateValue) {
__ mov(eax, FieldOperand(eax, JSDate::kValueOffset));
} else {
if (field_index < JSDate::kFirstUncachedField) {
Label stamp_mismatch;
__ mov(edx, Operand::StaticVariable(
ExternalReference::date_cache_stamp(masm->isolate())));
__ cmp(edx, FieldOperand(eax, JSDate::kCacheStampOffset));
__ j(not_equal, &stamp_mismatch, Label::kNear);
__ mov(eax, FieldOperand(
eax, JSDate::kValueOffset + field_index * kPointerSize));
__ ret(1 * kPointerSize);
__ bind(&stamp_mismatch);
}
FrameScope scope(masm, StackFrame::INTERNAL);
__ PrepareCallCFunction(2, ebx);
__ mov(Operand(esp, 0), eax);
__ mov(Operand(esp, 1 * kPointerSize),
Immediate(Smi::FromInt(field_index)));
__ CallCFunction(
ExternalReference::get_date_field_function(masm->isolate()), 2);
}
__ ret(1 * kPointerSize);
// 3. Raise a TypeError if the receiver is not a date.
__ bind(&receiver_not_date);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Move(ebx, Immediate(0));
__ EnterBuiltinFrame(esi, edi, ebx);
__ CallRuntime(Runtime::kThrowNotDateError);
// It's far from obvious, but this final trailing instruction after the call
// is required for StackFrame::LookupCode to work correctly. To illustrate
// why: if call were the final instruction in the code object, then the pc
// (== return address) would point beyond the code object when the stack is
// traversed. When we then try to look up the code object through
// StackFrame::LookupCode, we actually return the next code object that
// happens to be on the same page in memory.
// TODO(jgruber): A proper fix for this would be nice.
__ nop();
}
}
// static
void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -878,6 +878,14 @@ Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
return CallN(call_descriptor, target, args);
}
Node* CodeAssembler::CallCFunction2(MachineType return_type,
MachineType arg0_type,
MachineType arg1_type, Node* function,
Node* arg0, Node* arg1) {
return raw_assembler_->CallCFunction2(return_type, arg0_type, arg1_type,
function, arg0, arg1);
}
void CodeAssembler::Goto(CodeAssembler::Label* label) {
label->MergeVariables();
raw_assembler_->Goto(label->label_);
......
......@@ -421,6 +421,11 @@ class CodeAssembler {
Node* CallJS(Callable const& callable, Node* context, Node* function,
Node* receiver, Node* arg1, Node* arg2, size_t result_size = 1);
// Call to a C function with two arguments.
Node* CallCFunction2(MachineType return_type, MachineType arg0_type,
MachineType arg1_type, Node* function, Node* arg0,
Node* arg1);
// Exception handling support.
void GotoIfException(Node* node, Label* if_exception,
Variable* exception_var = nullptr);
......
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