diff options
Diffstat (limited to 'deps/v8/src/mips/code-stubs-mips.cc')
-rw-r--r-- | deps/v8/src/mips/code-stubs-mips.cc | 839 |
1 files changed, 342 insertions, 497 deletions
diff --git a/deps/v8/src/mips/code-stubs-mips.cc b/deps/v8/src/mips/code-stubs-mips.cc index 79af21940..2e8e6074b 100644 --- a/deps/v8/src/mips/code-stubs-mips.cc +++ b/deps/v8/src/mips/code-stubs-mips.cc @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "v8.h" +#include "src/v8.h" #if V8_TARGET_ARCH_MIPS -#include "bootstrapper.h" -#include "code-stubs.h" -#include "codegen.h" -#include "regexp-macro-assembler.h" -#include "stub-cache.h" +#include "src/bootstrapper.h" +#include "src/code-stubs.h" +#include "src/codegen.h" +#include "src/regexp-macro-assembler.h" +#include "src/stub-cache.h" namespace v8 { namespace internal { @@ -18,251 +18,196 @@ namespace internal { void FastNewClosureStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a2 }; - descriptor->register_param_count_ = 1; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - Runtime::FunctionForId(Runtime::kHiddenNewClosureFromStubFailure)->entry; + Register registers[] = { cp, a2 }; + descriptor->Initialize( + MajorKey(), ARRAY_SIZE(registers), registers, + Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry); } void FastNewContextStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a1 }; - descriptor->register_param_count_ = 1; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = NULL; + Register registers[] = { cp, a1 }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); } void ToNumberStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a0 }; - descriptor->register_param_count_ = 1; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = NULL; + Register registers[] = { cp, a0 }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); } void NumberToStringStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a0 }; - descriptor->register_param_count_ = 1; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - Runtime::FunctionForId(Runtime::kHiddenNumberToString)->entry; + Register registers[] = { cp, a0 }; + descriptor->Initialize( + MajorKey(), ARRAY_SIZE(registers), registers, + Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry); } void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a3, a2, a1 }; - descriptor->register_param_count_ = 3; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - Runtime::FunctionForId( - Runtime::kHiddenCreateArrayLiteralStubBailout)->entry; + Register registers[] = { cp, a3, a2, a1 }; + Representation representations[] = { + Representation::Tagged(), + Representation::Tagged(), + Representation::Smi(), + Representation::Tagged() }; + descriptor->Initialize( + MajorKey(), ARRAY_SIZE(registers), registers, + Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry, + representations); } void FastCloneShallowObjectStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a3, a2, a1, a0 }; - descriptor->register_param_count_ = 4; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - Runtime::FunctionForId(Runtime::kHiddenCreateObjectLiteral)->entry; + Register registers[] = { cp, a3, a2, a1, a0 }; + descriptor->Initialize( + MajorKey(), ARRAY_SIZE(registers), registers, + Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry); } void CreateAllocationSiteStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a2, a3 }; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = NULL; + Register registers[] = { cp, a2, a3 }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); } -void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( +void CallFunctionStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a1, a0 }; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); + UNIMPLEMENTED(); } -void KeyedLoadDictionaryElementStub::InitializeInterfaceDescriptor( +void CallConstructStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = {a1, a0 }; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); + UNIMPLEMENTED(); } void RegExpConstructResultStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a2, a1, a0 }; - descriptor->register_param_count_ = 3; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - Runtime::FunctionForId(Runtime::kHiddenRegExpConstructResult)->entry; -} - - -void LoadFieldStub::InitializeInterfaceDescriptor( - CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a0 }; - descriptor->register_param_count_ = 1; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = NULL; -} - - -void KeyedLoadFieldStub::InitializeInterfaceDescriptor( - CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a1 }; - descriptor->register_param_count_ = 1; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = NULL; -} - - -void StringLengthStub::InitializeInterfaceDescriptor( - CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a0, a2 }; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = NULL; -} - - -void KeyedStringLengthStub::InitializeInterfaceDescriptor( - CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a1, a0 }; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = NULL; -} - - -void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( - CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a2, a1, a0 }; - descriptor->register_param_count_ = 3; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure); + Register registers[] = { cp, a2, a1, a0 }; + descriptor->Initialize( + MajorKey(), ARRAY_SIZE(registers), registers, + Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry); } void TransitionElementsKindStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a0, a1 }; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers; + Register registers[] = { cp, a0, a1 }; Address entry = Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; - descriptor->deoptimization_handler_ = FUNCTION_ADDR(entry); + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, + FUNCTION_ADDR(entry)); } void CompareNilICStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a0 }; - descriptor->register_param_count_ = 1; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - FUNCTION_ADDR(CompareNilIC_Miss); + Register registers[] = { cp, a0 }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, + FUNCTION_ADDR(CompareNilIC_Miss)); descriptor->SetMissHandler( ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate())); } +const Register InterfaceDescriptor::ContextRegister() { return cp; } + + static void InitializeArrayConstructorDescriptor( - CodeStubInterfaceDescriptor* descriptor, + CodeStub::Major major, CodeStubInterfaceDescriptor* descriptor, int constant_stack_parameter_count) { // register state + // cp -- context // a0 -- number of arguments // a1 -- function // a2 -- allocation site with elements kind - static Register registers_variable_args[] = { a1, a2, a0 }; - static Register registers_no_args[] = { a1, a2 }; + Address deopt_handler = Runtime::FunctionForId( + Runtime::kArrayConstructor)->entry; if (constant_stack_parameter_count == 0) { - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers_no_args; + Register registers[] = { cp, a1, a2 }; + descriptor->Initialize(major, ARRAY_SIZE(registers), registers, + deopt_handler, NULL, constant_stack_parameter_count, + JS_FUNCTION_STUB_MODE); } else { // stack param count needs (constructor pointer, and single argument) - descriptor->handler_arguments_mode_ = PASS_ARGUMENTS; - descriptor->stack_parameter_count_ = a0; - descriptor->register_param_count_ = 3; - descriptor->register_params_ = registers_variable_args; + Register registers[] = { cp, a1, a2, a0 }; + Representation representations[] = { + Representation::Tagged(), + Representation::Tagged(), + Representation::Tagged(), + Representation::Integer32() }; + descriptor->Initialize(major, ARRAY_SIZE(registers), registers, a0, + deopt_handler, representations, + constant_stack_parameter_count, + JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); } - - descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; - descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; - descriptor->deoptimization_handler_ = - Runtime::FunctionForId(Runtime::kHiddenArrayConstructor)->entry; } static void InitializeInternalArrayConstructorDescriptor( - CodeStubInterfaceDescriptor* descriptor, + CodeStub::Major major, CodeStubInterfaceDescriptor* descriptor, int constant_stack_parameter_count) { // register state + // cp -- context // a0 -- number of arguments // a1 -- constructor function - static Register registers_variable_args[] = { a1, a0 }; - static Register registers_no_args[] = { a1 }; + Address deopt_handler = Runtime::FunctionForId( + Runtime::kInternalArrayConstructor)->entry; if (constant_stack_parameter_count == 0) { - descriptor->register_param_count_ = 1; - descriptor->register_params_ = registers_no_args; + Register registers[] = { cp, a1 }; + descriptor->Initialize(major, ARRAY_SIZE(registers), registers, + deopt_handler, NULL, constant_stack_parameter_count, + JS_FUNCTION_STUB_MODE); } else { // stack param count needs (constructor pointer, and single argument) - descriptor->handler_arguments_mode_ = PASS_ARGUMENTS; - descriptor->stack_parameter_count_ = a0; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers_variable_args; + Register registers[] = { cp, a1, a0 }; + Representation representations[] = { + Representation::Tagged(), + Representation::Tagged(), + Representation::Integer32() }; + descriptor->Initialize(major, ARRAY_SIZE(registers), registers, a0, + deopt_handler, representations, + constant_stack_parameter_count, + JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); } - - descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; - descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; - descriptor->deoptimization_handler_ = - Runtime::FunctionForId(Runtime::kHiddenInternalArrayConstructor)->entry; } void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - InitializeArrayConstructorDescriptor(descriptor, 0); + InitializeArrayConstructorDescriptor(MajorKey(), descriptor, 0); } void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - InitializeArrayConstructorDescriptor(descriptor, 1); + InitializeArrayConstructorDescriptor(MajorKey(), descriptor, 1); } void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - InitializeArrayConstructorDescriptor(descriptor, -1); + InitializeArrayConstructorDescriptor(MajorKey(), descriptor, -1); } void ToBooleanStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a0 }; - descriptor->register_param_count_ = 1; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - FUNCTION_ADDR(ToBooleanIC_Miss); + Register registers[] = { cp, a0 }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, + FUNCTION_ADDR(ToBooleanIC_Miss)); descriptor->SetMissHandler( ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate())); } @@ -270,48 +215,27 @@ void ToBooleanStub::InitializeInterfaceDescriptor( void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - InitializeInternalArrayConstructorDescriptor(descriptor, 0); + InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, 0); } void InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - InitializeInternalArrayConstructorDescriptor(descriptor, 1); + InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, 1); } void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - InitializeInternalArrayConstructorDescriptor(descriptor, -1); -} - - -void StoreGlobalStub::InitializeInterfaceDescriptor( - CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a1, a2, a0 }; - descriptor->register_param_count_ = 3; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - FUNCTION_ADDR(StoreIC_MissFromStubFailure); -} - - -void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor( - CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a0, a3, a1, a2 }; - descriptor->register_param_count_ = 4; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss); + InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, -1); } void BinaryOpICStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a1, a0 }; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = FUNCTION_ADDR(BinaryOpIC_Miss); + Register registers[] = { cp, a1, a0 }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, + FUNCTION_ADDR(BinaryOpIC_Miss)); descriptor->SetMissHandler( ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate())); } @@ -319,21 +243,17 @@ void BinaryOpICStub::InitializeInterfaceDescriptor( void BinaryOpWithAllocationSiteStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a2, a1, a0 }; - descriptor->register_param_count_ = 3; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite); + Register registers[] = { cp, a2, a1, a0 }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, + FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite)); } void StringAddStub::InitializeInterfaceDescriptor( CodeStubInterfaceDescriptor* descriptor) { - static Register registers[] = { a1, a0 }; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers; - descriptor->deoptimization_handler_ = - Runtime::FunctionForId(Runtime::kHiddenStringAdd)->entry; + Register registers[] = { cp, a1, a0 }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, + Runtime::FunctionForId(Runtime::kStringAdd)->entry); } @@ -341,82 +261,72 @@ void CallDescriptors::InitializeForIsolate(Isolate* isolate) { { CallInterfaceDescriptor* descriptor = isolate->call_descriptor(Isolate::ArgumentAdaptorCall); - static Register registers[] = { a1, // JSFunction - cp, // context - a0, // actual number of arguments - a2, // expected number of arguments + Register registers[] = { cp, // context, + a1, // JSFunction + a0, // actual number of arguments + a2, // expected number of arguments }; - static Representation representations[] = { - Representation::Tagged(), // JSFunction + Representation representations[] = { Representation::Tagged(), // context + Representation::Tagged(), // JSFunction Representation::Integer32(), // actual number of arguments Representation::Integer32(), // expected number of arguments }; - descriptor->register_param_count_ = 4; - descriptor->register_params_ = registers; - descriptor->param_representations_ = representations; + descriptor->Initialize(ARRAY_SIZE(registers), registers, representations); } { CallInterfaceDescriptor* descriptor = isolate->call_descriptor(Isolate::KeyedCall); - static Register registers[] = { cp, // context - a2, // key + Register registers[] = { cp, // context + a2, // key }; - static Representation representations[] = { + Representation representations[] = { Representation::Tagged(), // context Representation::Tagged(), // key }; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers; - descriptor->param_representations_ = representations; + descriptor->Initialize(ARRAY_SIZE(registers), registers, representations); } { CallInterfaceDescriptor* descriptor = isolate->call_descriptor(Isolate::NamedCall); - static Register registers[] = { cp, // context - a2, // name + Register registers[] = { cp, // context + a2, // name }; - static Representation representations[] = { + Representation representations[] = { Representation::Tagged(), // context Representation::Tagged(), // name }; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers; - descriptor->param_representations_ = representations; + descriptor->Initialize(ARRAY_SIZE(registers), registers, representations); } { CallInterfaceDescriptor* descriptor = isolate->call_descriptor(Isolate::CallHandler); - static Register registers[] = { cp, // context - a0, // receiver + Register registers[] = { cp, // context + a0, // receiver }; - static Representation representations[] = { + Representation representations[] = { Representation::Tagged(), // context Representation::Tagged(), // receiver }; - descriptor->register_param_count_ = 2; - descriptor->register_params_ = registers; - descriptor->param_representations_ = representations; + descriptor->Initialize(ARRAY_SIZE(registers), registers, representations); } { CallInterfaceDescriptor* descriptor = isolate->call_descriptor(Isolate::ApiFunctionCall); - static Register registers[] = { a0, // callee - t0, // call_data - a2, // holder - a1, // api_function_address - cp, // context + Register registers[] = { cp, // context + a0, // callee + t0, // call_data + a2, // holder + a1, // api_function_address }; - static Representation representations[] = { + Representation representations[] = { + Representation::Tagged(), // context Representation::Tagged(), // callee Representation::Tagged(), // call_data Representation::Tagged(), // holder Representation::External(), // api_function_address - Representation::Tagged(), // context }; - descriptor->register_param_count_ = 5; - descriptor->register_params_ = registers; - descriptor->param_representations_ = representations; + descriptor->Initialize(ARRAY_SIZE(registers), registers, representations); } } @@ -443,21 +353,22 @@ void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { isolate()->counters()->code_stubs()->Increment(); CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(); - int param_count = descriptor->register_param_count_; + int param_count = descriptor->GetEnvironmentParameterCount(); { // Call the runtime system in a fresh internal frame. FrameScope scope(masm, StackFrame::INTERNAL); - ASSERT(descriptor->register_param_count_ == 0 || - a0.is(descriptor->register_params_[param_count - 1])); + DCHECK(param_count == 0 || + a0.is(descriptor->GetEnvironmentParameterRegister( + param_count - 1))); // Push arguments, adjust sp. __ Subu(sp, sp, Operand(param_count * kPointerSize)); for (int i = 0; i < param_count; ++i) { // Store argument to stack. - __ sw(descriptor->register_params_[i], + __ sw(descriptor->GetEnvironmentParameterRegister(i), MemOperand(sp, (param_count-1-i) * kPointerSize)); } ExternalReference miss = descriptor->miss_handler(); - __ CallExternalReference(miss, descriptor->register_param_count_); + __ CallExternalReference(miss, param_count); } __ Ret(); @@ -492,8 +403,8 @@ class ConvertToDoubleStub : public PlatformCodeStub { class ModeBits: public BitField<OverwriteMode, 0, 2> {}; class OpBits: public BitField<Token::Value, 2, 14> {}; - Major MajorKey() { return ConvertToDouble; } - int MinorKey() { + Major MajorKey() const { return ConvertToDouble; } + int MinorKey() const { // Encode the parameters in a unique 16 bit value. return result1_.code() + (result2_.code() << 4) + @@ -739,7 +650,7 @@ void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { // but it just ends up combining harmlessly with the last digit of the // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get // the most significant 1 to hit the last bit of the 12 bit sign and exponent. - ASSERT(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); + DCHECK(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; __ srl(at, the_int_, shift_distance); __ or_(scratch_, scratch_, at); @@ -800,7 +711,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, __ Branch(&return_equal, ne, t4, Operand(ODDBALL_TYPE)); __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); __ Branch(&return_equal, ne, a0, Operand(t2)); - ASSERT(is_int16(GREATER) && is_int16(LESS)); + DCHECK(is_int16(GREATER) && is_int16(LESS)); __ Ret(USE_DELAY_SLOT); if (cc == le) { // undefined <= undefined should fail. @@ -814,7 +725,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, } __ bind(&return_equal); - ASSERT(is_int16(GREATER) && is_int16(LESS)); + DCHECK(is_int16(GREATER) && is_int16(LESS)); __ Ret(USE_DELAY_SLOT); if (cc == less) { __ li(v0, Operand(GREATER)); // Things aren't less than themselves. @@ -853,7 +764,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, if (cc != eq) { // All-zero means Infinity means equal. __ Ret(eq, v0, Operand(zero_reg)); - ASSERT(is_int16(GREATER) && is_int16(LESS)); + DCHECK(is_int16(GREATER) && is_int16(LESS)); __ Ret(USE_DELAY_SLOT); if (cc == le) { __ li(v0, Operand(GREATER)); // NaN <= NaN should fail. @@ -874,7 +785,7 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm, Label* both_loaded_as_doubles, Label* slow, bool strict) { - ASSERT((lhs.is(a0) && rhs.is(a1)) || + DCHECK((lhs.is(a0) && rhs.is(a1)) || (lhs.is(a1) && rhs.is(a0))); Label lhs_is_smi; @@ -992,7 +903,7 @@ static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, Register rhs, Label* possible_strings, Label* not_both_strings) { - ASSERT((lhs.is(a0) && rhs.is(a1)) || + DCHECK((lhs.is(a0) && rhs.is(a1)) || (lhs.is(a1) && rhs.is(a0))); // a2 is object type of rhs. @@ -1083,7 +994,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { // If either is a Smi (we know that not both are), then they can only // be strictly equal if the other is a HeapNumber. STATIC_ASSERT(kSmiTag == 0); - ASSERT_EQ(0, Smi::FromInt(0)); + DCHECK_EQ(0, Smi::FromInt(0)); __ And(t2, lhs, Operand(rhs)); __ JumpIfNotSmi(t2, ¬_smis, t0); // One operand is a smi. EmitSmiNonsmiComparison generates code that can: @@ -1127,7 +1038,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { __ bind(&nan); // NaN comparisons always fail. // Load whatever we need in v0 to make the comparison fail. - ASSERT(is_int16(GREATER) && is_int16(LESS)); + DCHECK(is_int16(GREATER) && is_int16(LESS)); __ Ret(USE_DELAY_SLOT); if (cc == lt || cc == le) { __ li(v0, Operand(GREATER)); @@ -1209,7 +1120,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { if (cc == lt || cc == le) { ncr = GREATER; } else { - ASSERT(cc == gt || cc == ge); // Remaining cases. + DCHECK(cc == gt || cc == ge); // Remaining cases. ncr = LESS; } __ li(a0, Operand(Smi::FromInt(ncr))); @@ -1228,11 +1139,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { void StoreRegistersStateStub::Generate(MacroAssembler* masm) { __ mov(t9, ra); __ pop(ra); - if (save_doubles_ == kSaveFPRegs) { - __ PushSafepointRegistersAndDoubles(); - } else { - __ PushSafepointRegisters(); - } + __ PushSafepointRegisters(); __ Jump(t9); } @@ -1240,12 +1147,7 @@ void StoreRegistersStateStub::Generate(MacroAssembler* masm) { void RestoreRegistersStateStub::Generate(MacroAssembler* masm) { __ mov(t9, ra); __ pop(ra); - __ StoreToSafepointRegisterSlot(t9, t9); - if (save_doubles_ == kSaveFPRegs) { - __ PopSafepointRegistersAndDoubles(); - } else { - __ PopSafepointRegisters(); - } + __ PopSafepointRegisters(); __ Jump(t9); } @@ -1460,7 +1362,7 @@ void MathPowStub::Generate(MacroAssembler* masm) { if (exponent_type_ == ON_STACK) { // The arguments are still on the stack. __ bind(&call_runtime); - __ TailCallRuntime(Runtime::kHiddenMathPow, 2, 1); + __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); // The stub is called from non-optimized code, which expects the result // as heap number in exponent. @@ -1469,7 +1371,7 @@ void MathPowStub::Generate(MacroAssembler* masm) { heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); __ sdc1(double_result, FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); - ASSERT(heapnumber.is(v0)); + DCHECK(heapnumber.is(v0)); __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); __ DropAndRet(2); } else { @@ -1511,23 +1413,15 @@ void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { } -void StoreRegistersStateStub::GenerateAheadOfTime( - Isolate* isolate) { - StoreRegistersStateStub stub1(isolate, kDontSaveFPRegs); - stub1.GetCode(); - // Hydrogen code stubs need stub2 at snapshot time. - StoreRegistersStateStub stub2(isolate, kSaveFPRegs); - stub2.GetCode(); +void StoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { + StoreRegistersStateStub stub(isolate); + stub.GetCode(); } -void RestoreRegistersStateStub::GenerateAheadOfTime( - Isolate* isolate) { - RestoreRegistersStateStub stub1(isolate, kDontSaveFPRegs); - stub1.GetCode(); - // Hydrogen code stubs need stub2 at snapshot time. - RestoreRegistersStateStub stub2(isolate, kSaveFPRegs); - stub2.GetCode(); +void RestoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { + RestoreRegistersStateStub stub(isolate); + stub.GetCode(); } @@ -1624,7 +1518,7 @@ void CEntryStub::Generate(MacroAssembler* masm) { // Set up sp in the delay slot. masm->addiu(sp, sp, -kCArgsSlotsSize); // Make sure the stored 'ra' points to this position. - ASSERT_EQ(kNumInstructionsToJump, + DCHECK_EQ(kNumInstructionsToJump, masm->InstructionsGeneratedSince(&find_ra)); } @@ -1875,9 +1769,9 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { // in the safepoint slot for register t0. void InstanceofStub::Generate(MacroAssembler* masm) { // Call site inlining and patching implies arguments in registers. - ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck()); + DCHECK(HasArgsInRegisters() || !HasCallSiteInlineCheck()); // ReturnTrueFalse is only implemented for inlined call sites. - ASSERT(!ReturnTrueFalseObject() || HasCallSiteInlineCheck()); + DCHECK(!ReturnTrueFalseObject() || HasCallSiteInlineCheck()); // Fixed register usage throughout the stub: const Register object = a0; // Object (lhs). @@ -1927,7 +1821,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) { __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); } else { - ASSERT(HasArgsInRegisters()); + DCHECK(HasArgsInRegisters()); // Patch the (relocated) inlined map check. // The offset was stored in t0 safepoint slot. @@ -1957,7 +1851,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) { __ Branch(&loop); __ bind(&is_instance); - ASSERT(Smi::FromInt(0) == 0); + DCHECK(Smi::FromInt(0) == 0); if (!HasCallSiteInlineCheck()) { __ mov(v0, zero_reg); __ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); @@ -1969,7 +1863,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) { __ PatchRelocatedValue(inline_site, scratch, v0); if (!ReturnTrueFalseObject()) { - ASSERT_EQ(Smi::FromInt(0), 0); + DCHECK_EQ(Smi::FromInt(0), 0); __ mov(v0, zero_reg); } } @@ -2045,31 +1939,12 @@ void InstanceofStub::Generate(MacroAssembler* masm) { void FunctionPrototypeStub::Generate(MacroAssembler* masm) { Label miss; - Register receiver; - if (kind() == Code::KEYED_LOAD_IC) { - // ----------- S t a t e ------------- - // -- ra : return address - // -- a0 : key - // -- a1 : receiver - // ----------------------------------- - __ Branch(&miss, ne, a0, - Operand(isolate()->factory()->prototype_string())); - receiver = a1; - } else { - ASSERT(kind() == Code::LOAD_IC); - // ----------- S t a t e ------------- - // -- a2 : name - // -- ra : return address - // -- a0 : receiver - // -- sp[0] : receiver - // ----------------------------------- - receiver = a0; - } - - StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, a3, t0, &miss); + Register receiver = LoadIC::ReceiverRegister(); + NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, a3, + t0, &miss); __ bind(&miss); - StubCompiler::TailCallBuiltin( - masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); + PropertyAccessCompiler::TailCallBuiltin( + masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC)); } @@ -2154,7 +2029,7 @@ void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { __ sw(a3, MemOperand(sp, 1 * kPointerSize)); __ bind(&runtime); - __ TailCallRuntime(Runtime::kHiddenNewArgumentsFast, 3, 1); + __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); } @@ -2209,7 +2084,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { FixedArray::kHeaderSize + 2 * kPointerSize; // If there are no mapped parameters, we do not need the parameter_map. Label param_map_size; - ASSERT_EQ(0, Smi::FromInt(0)); + DCHECK_EQ(0, Smi::FromInt(0)); __ Branch(USE_DELAY_SLOT, ¶m_map_size, eq, a1, Operand(zero_reg)); __ mov(t5, zero_reg); // In delay slot: param map size = 0 when a1 == 0. __ sll(t5, a1, 1); @@ -2228,12 +2103,12 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { __ Allocate(t5, v0, a3, t0, &runtime, TAG_OBJECT); // v0 = address of new object(s) (tagged) - // a2 = argument count (tagged) + // a2 = argument count (smi-tagged) // Get the arguments boilerplate from the current native context into t0. const int kNormalOffset = - Context::SlotOffset(Context::SLOPPY_ARGUMENTS_BOILERPLATE_INDEX); + Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); const int kAliasedOffset = - Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX); + Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX); __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); __ lw(t0, FieldMemOperand(t0, GlobalObject::kNativeContextOffset)); @@ -2248,22 +2123,23 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { // v0 = address of new object (tagged) // a1 = mapped parameter count (tagged) - // a2 = argument count (tagged) - // t0 = address of boilerplate object (tagged) - // Copy the JS object part. - for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { - __ lw(a3, FieldMemOperand(t0, i)); - __ sw(a3, FieldMemOperand(v0, i)); - } + // a2 = argument count (smi-tagged) + // t0 = address of arguments map (tagged) + __ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset)); + __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex); + __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset)); + __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); // Set up the callee in-object property. STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); __ lw(a3, MemOperand(sp, 2 * kPointerSize)); + __ AssertNotSmi(a3); const int kCalleeOffset = JSObject::kHeaderSize + Heap::kArgumentsCalleeIndex * kPointerSize; __ sw(a3, FieldMemOperand(v0, kCalleeOffset)); // Use the length (smi tagged) and set that as an in-object property too. + __ AssertSmi(a2); STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); const int kLengthOffset = JSObject::kHeaderSize + Heap::kArgumentsLengthIndex * kPointerSize; @@ -2373,7 +2249,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { // a2 = argument count (tagged) __ bind(&runtime); __ sw(a2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count. - __ TailCallRuntime(Runtime::kHiddenNewArgumentsFast, 3, 1); + __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); } @@ -2422,15 +2298,18 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Get the arguments boilerplate from the current native context. __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); __ lw(t0, FieldMemOperand(t0, GlobalObject::kNativeContextOffset)); - __ lw(t0, MemOperand(t0, Context::SlotOffset( - Context::STRICT_ARGUMENTS_BOILERPLATE_INDEX))); + __ lw(t0, MemOperand( + t0, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX))); - // Copy the JS object part. - __ CopyFields(v0, t0, a3.bit(), JSObject::kHeaderSize / kPointerSize); + __ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset)); + __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex); + __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset)); + __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); // Get the length (smi tagged) and set that as an in-object property too. STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); __ lw(a1, MemOperand(sp, 0 * kPointerSize)); + __ AssertSmi(a1); __ sw(a1, FieldMemOperand(v0, JSObject::kHeaderSize + Heap::kArgumentsLengthIndex * kPointerSize)); @@ -2471,7 +2350,7 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Do the runtime call to allocate the arguments object. __ bind(&runtime); - __ TailCallRuntime(Runtime::kHiddenNewStrictArgumentsFast, 3, 1); + __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1); } @@ -2480,7 +2359,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { // time or if regexp entry in generated code is turned off runtime switch or // at compilation. #ifdef V8_INTERPRETED_REGEXP - __ TailCallRuntime(Runtime::kHiddenRegExpExec, 4, 1); + __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1); #else // V8_INTERPRETED_REGEXP // Stack frame on entry. @@ -2618,8 +2497,8 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT(kSeqStringTag == 0); __ And(at, a0, Operand(kStringRepresentationMask)); // The underlying external string is never a short external string. - STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength); - STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength); + STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); + STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); __ Branch(&external_string, ne, at, Operand(zero_reg)); // Go to (7). // (5) Sequential string. Load regexp code according to encoding. @@ -2870,7 +2749,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { // Do the runtime call to execute the regexp. __ bind(&runtime); - __ TailCallRuntime(Runtime::kHiddenRegExpExec, 4, 1); + __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1); // Deferred code for string handling. // (6) Not a long external string? If yes, go to (8). @@ -2926,9 +2805,9 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) { // a3 : slot in feedback vector (Smi) Label initialize, done, miss, megamorphic, not_array_function; - ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), + DCHECK_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), masm->isolate()->heap()->megamorphic_symbol()); - ASSERT_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()), + DCHECK_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()), masm->isolate()->heap()->uninitialized_symbol()); // Load the cache state into t0. @@ -3070,11 +2949,13 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { } -void CallFunctionStub::Generate(MacroAssembler* masm) { +static void CallFunctionNoFeedback(MacroAssembler* masm, + int argc, bool needs_checks, + bool call_as_method) { // a1 : the function to call Label slow, non_function, wrap, cont; - if (NeedsChecks()) { + if (needs_checks) { // Check that the function is really a JavaScript function. // a1: pushed function (to be verified) __ JumpIfSmi(a1, &non_function); @@ -3086,18 +2967,17 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { // Fast-case: Invoke the function now. // a1: pushed function - int argc = argc_; ParameterCount actual(argc); - if (CallAsMethod()) { - if (NeedsChecks()) { + if (call_as_method) { + if (needs_checks) { EmitContinueIfStrictOrNative(masm, &cont); } // Compute the receiver in sloppy mode. __ lw(a3, MemOperand(sp, argc * kPointerSize)); - if (NeedsChecks()) { + if (needs_checks) { __ JumpIfSmi(a3, &wrap); __ GetObjectType(a3, t0, t0); __ Branch(&wrap, lt, t0, Operand(FIRST_SPEC_OBJECT_TYPE)); @@ -3110,13 +2990,13 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { __ InvokeFunction(a1, actual, JUMP_FUNCTION, NullCallWrapper()); - if (NeedsChecks()) { + if (needs_checks) { // Slow-case: Non-function called. __ bind(&slow); EmitSlowCase(masm, argc, &non_function); } - if (CallAsMethod()) { + if (call_as_method) { __ bind(&wrap); // Wrap the receiver and patch it back onto the stack. EmitWrapCase(masm, argc, &cont); @@ -3124,6 +3004,11 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { } +void CallFunctionStub::Generate(MacroAssembler* masm) { + CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); +} + + void CallConstructStub::Generate(MacroAssembler* masm) { // a0 : number of arguments // a1 : the function to call @@ -3183,8 +3068,8 @@ void CallConstructStub::Generate(MacroAssembler* masm) { __ bind(&do_call); // Set expected number of arguments to zero (not changing r0). __ li(a2, Operand(0, RelocInfo::NONE32)); - __ Jump(isolate()->builtins()->ArgumentsAdaptorTrampoline(), - RelocInfo::CODE_TARGET); + __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), + RelocInfo::CODE_TARGET); } @@ -3197,6 +3082,44 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { } +void CallIC_ArrayStub::Generate(MacroAssembler* masm) { + // a1 - function + // a3 - slot id + Label miss; + + EmitLoadTypeFeedbackVector(masm, a2); + + __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, at); + __ Branch(&miss, ne, a1, Operand(at)); + + __ li(a0, Operand(arg_count())); + __ sll(at, a3, kPointerSizeLog2 - kSmiTagSize); + __ Addu(at, a2, Operand(at)); + __ lw(t0, FieldMemOperand(at, FixedArray::kHeaderSize)); + + // Verify that t0 contains an AllocationSite + __ lw(t1, FieldMemOperand(t0, HeapObject::kMapOffset)); + __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); + __ Branch(&miss, ne, t1, Operand(at)); + + __ mov(a2, t0); + ArrayConstructorStub stub(masm->isolate(), arg_count()); + __ TailCallStub(&stub); + + __ bind(&miss); + GenerateMiss(masm, IC::kCallIC_Customization_Miss); + + // The slow case, we need this no matter what to complete a call after a miss. + CallFunctionNoFeedback(masm, + arg_count(), + true, + CallAsMethod()); + + // Unreachable. + __ stop("Unexpected code address"); +} + + void CallICStub::Generate(MacroAssembler* masm) { // r1 - function // r3 - slot id (Smi) @@ -3246,7 +3169,11 @@ void CallICStub::Generate(MacroAssembler* masm) { __ Branch(&miss, eq, t0, Operand(at)); if (!FLAG_trace_ic) { - // We are going megamorphic, and we don't want to visit the runtime. + // We are going megamorphic. If the feedback is a JSFunction, it is fine + // to handle it here. More complex cases are dealt with in the runtime. + __ AssertNotSmi(t0); + __ GetObjectType(t0, t1, t1); + __ Branch(&miss, ne, t1, Operand(JS_FUNCTION_TYPE)); __ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize); __ Addu(t0, a2, Operand(t0)); __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex); @@ -3256,7 +3183,7 @@ void CallICStub::Generate(MacroAssembler* masm) { // We are here because tracing is on or we are going monomorphic. __ bind(&miss); - GenerateMiss(masm); + GenerateMiss(masm, IC::kCallIC_Miss); // the slow case __ bind(&slow_start); @@ -3271,7 +3198,7 @@ void CallICStub::Generate(MacroAssembler* masm) { } -void CallICStub::GenerateMiss(MacroAssembler* masm) { +void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) { // Get the receiver of the function from the stack; 1 ~ return address. __ lw(t0, MemOperand(sp, (state_.arg_count() + 1) * kPointerSize)); @@ -3282,7 +3209,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) { __ Push(t0, a1, a2, a3); // Call the entry. - ExternalReference miss = ExternalReference(IC_Utility(IC::kCallIC_Miss), + ExternalReference miss = ExternalReference(IC_Utility(id), masm->isolate()); __ CallExternalReference(miss, 4); @@ -3299,9 +3226,9 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { Label got_char_code; Label sliced_string; - ASSERT(!t0.is(index_)); - ASSERT(!t0.is(result_)); - ASSERT(!t0.is(object_)); + DCHECK(!t0.is(index_)); + DCHECK(!t0.is(result_)); + DCHECK(!t0.is(object_)); // If the receiver is a smi trigger the non-string case. __ JumpIfSmi(object_, receiver_not_string_); @@ -3354,9 +3281,9 @@ void StringCharCodeAtGenerator::GenerateSlow( if (index_flags_ == STRING_INDEX_IS_NUMBER) { __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); } else { - ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); + DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); // NumberToSmi discards numbers that are not exact integers. - __ CallRuntime(Runtime::kHiddenNumberToSmi, 1); + __ CallRuntime(Runtime::kNumberToSmi, 1); } // Save the conversion result before the pop instructions below @@ -3380,7 +3307,7 @@ void StringCharCodeAtGenerator::GenerateSlow( call_helper.BeforeCall(masm); __ sll(index_, index_, kSmiTagSize); __ Push(object_, index_); - __ CallRuntime(Runtime::kHiddenStringCharCodeAt, 2); + __ CallRuntime(Runtime::kStringCharCodeAtRT, 2); __ Move(result_, v0); @@ -3397,12 +3324,12 @@ void StringCharCodeAtGenerator::GenerateSlow( void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { // Fast case of Heap::LookupSingleCharacterStringFromCode. - ASSERT(!t0.is(result_)); - ASSERT(!t0.is(code_)); + DCHECK(!t0.is(result_)); + DCHECK(!t0.is(code_)); STATIC_ASSERT(kSmiTag == 0); STATIC_ASSERT(kSmiShiftSize == 0); - ASSERT(IsPowerOf2(String::kMaxOneByteCharCode + 1)); + DCHECK(IsPowerOf2(String::kMaxOneByteCharCode + 1)); __ And(t0, code_, Operand(kSmiTagMask | @@ -3445,119 +3372,42 @@ enum CopyCharactersFlags { }; -void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm, - Register dest, - Register src, - Register count, - Register scratch1, - Register scratch2, - Register scratch3, - Register scratch4, - Register scratch5, - int flags) { - bool ascii = (flags & COPY_ASCII) != 0; - bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0; - - if (dest_always_aligned && FLAG_debug_code) { - // Check that destination is actually word aligned if the flag says - // that it is. - __ And(scratch4, dest, Operand(kPointerAlignmentMask)); +void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, + Register dest, + Register src, + Register count, + Register scratch, + String::Encoding encoding) { + if (FLAG_debug_code) { + // Check that destination is word aligned. + __ And(scratch, dest, Operand(kPointerAlignmentMask)); __ Check(eq, kDestinationOfCopyNotAligned, - scratch4, + scratch, Operand(zero_reg)); } - const int kReadAlignment = 4; - const int kReadAlignmentMask = kReadAlignment - 1; - // Ensure that reading an entire aligned word containing the last character - // of a string will not read outside the allocated area (because we pad up - // to kObjectAlignment). - STATIC_ASSERT(kObjectAlignment >= kReadAlignment); // Assumes word reads and writes are little endian. // Nothing to do for zero characters. Label done; - if (!ascii) { - __ addu(count, count, count); - } - __ Branch(&done, eq, count, Operand(zero_reg)); - - Label byte_loop; - // Must copy at least eight bytes, otherwise just do it one byte at a time. - __ Subu(scratch1, count, Operand(8)); - __ Addu(count, dest, Operand(count)); - Register limit = count; // Read until src equals this. - __ Branch(&byte_loop, lt, scratch1, Operand(zero_reg)); - - if (!dest_always_aligned) { - // Align dest by byte copying. Copies between zero and three bytes. - __ And(scratch4, dest, Operand(kReadAlignmentMask)); - Label dest_aligned; - __ Branch(&dest_aligned, eq, scratch4, Operand(zero_reg)); - Label aligned_loop; - __ bind(&aligned_loop); - __ lbu(scratch1, MemOperand(src)); - __ addiu(src, src, 1); - __ sb(scratch1, MemOperand(dest)); - __ addiu(dest, dest, 1); - __ addiu(scratch4, scratch4, 1); - __ Branch(&aligned_loop, le, scratch4, Operand(kReadAlignmentMask)); - __ bind(&dest_aligned); - } - - Label simple_loop; - - __ And(scratch4, src, Operand(kReadAlignmentMask)); - __ Branch(&simple_loop, eq, scratch4, Operand(zero_reg)); - - // Loop for src/dst that are not aligned the same way. - // This loop uses lwl and lwr instructions. These instructions - // depend on the endianness, and the implementation assumes little-endian. - { - Label loop; - __ bind(&loop); - if (kArchEndian == kBig) { - __ lwl(scratch1, MemOperand(src)); - __ Addu(src, src, Operand(kReadAlignment)); - __ lwr(scratch1, MemOperand(src, -1)); - } else { - __ lwr(scratch1, MemOperand(src)); - __ Addu(src, src, Operand(kReadAlignment)); - __ lwl(scratch1, MemOperand(src, -1)); - } - __ sw(scratch1, MemOperand(dest)); - __ Addu(dest, dest, Operand(kReadAlignment)); - __ Subu(scratch2, limit, dest); - __ Branch(&loop, ge, scratch2, Operand(kReadAlignment)); + if (encoding == String::TWO_BYTE_ENCODING) { + __ Addu(count, count, count); } - __ Branch(&byte_loop); - - // Simple loop. - // Copy words from src to dest, until less than four bytes left. - // Both src and dest are word aligned. - __ bind(&simple_loop); - { - Label loop; - __ bind(&loop); - __ lw(scratch1, MemOperand(src)); - __ Addu(src, src, Operand(kReadAlignment)); - __ sw(scratch1, MemOperand(dest)); - __ Addu(dest, dest, Operand(kReadAlignment)); - __ Subu(scratch2, limit, dest); - __ Branch(&loop, ge, scratch2, Operand(kReadAlignment)); - } + Register limit = count; // Read until dest equals this. + __ Addu(limit, dest, Operand(count)); + Label loop_entry, loop; // Copy bytes from src to dest until dest hits limit. - __ bind(&byte_loop); - // Test if dest has already reached the limit. - __ Branch(&done, ge, dest, Operand(limit)); - __ lbu(scratch1, MemOperand(src)); - __ addiu(src, src, 1); - __ sb(scratch1, MemOperand(dest)); - __ addiu(dest, dest, 1); - __ Branch(&byte_loop); + __ Branch(&loop_entry); + __ bind(&loop); + __ lbu(scratch, MemOperand(src)); + __ Addu(src, src, Operand(1)); + __ sb(scratch, MemOperand(dest)); + __ Addu(dest, dest, Operand(1)); + __ bind(&loop_entry); + __ Branch(&loop, lt, dest, Operand(limit)); __ bind(&done); } @@ -3759,7 +3609,7 @@ void SubStringStub::Generate(MacroAssembler* masm) { // Handle external string. // Rule out short external strings. - STATIC_CHECK(kShortExternalStringTag != 0); + STATIC_ASSERT(kShortExternalStringTag != 0); __ And(t0, a1, Operand(kShortExternalStringTag)); __ Branch(&runtime, ne, t0, Operand(zero_reg)); __ lw(t1, FieldMemOperand(t1, ExternalString::kResourceDataOffset)); @@ -3791,8 +3641,8 @@ void SubStringStub::Generate(MacroAssembler* masm) { // a2: result string length // t1: first character of substring to copy STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); - StringHelper::GenerateCopyCharactersLong( - masm, a1, t1, a2, a3, t0, t2, t3, t4, COPY_ASCII | DEST_ALWAYS_ALIGNED); + StringHelper::GenerateCopyCharacters( + masm, a1, t1, a2, a3, String::ONE_BYTE_ENCODING); __ jmp(&return_v0); // Allocate and copy the resulting two-byte string. @@ -3811,8 +3661,8 @@ void SubStringStub::Generate(MacroAssembler* masm) { // a2: result length. // t1: first character of substring to copy. STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); - StringHelper::GenerateCopyCharactersLong( - masm, a1, t1, a2, a3, t0, t2, t3, t4, DEST_ALWAYS_ALIGNED); + StringHelper::GenerateCopyCharacters( + masm, a1, t1, a2, a3, String::TWO_BYTE_ENCODING); __ bind(&return_v0); Counters* counters = isolate()->counters(); @@ -3821,7 +3671,7 @@ void SubStringStub::Generate(MacroAssembler* masm) { // Just jump to runtime to create the sub string. __ bind(&runtime); - __ TailCallRuntime(Runtime::kHiddenSubString, 3, 1); + __ TailCallRuntime(Runtime::kSubString, 3, 1); __ bind(&single_char); // v0: original string @@ -3851,7 +3701,7 @@ void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, __ lw(scratch2, FieldMemOperand(right, String::kLengthOffset)); __ Branch(&check_zero_length, eq, length, Operand(scratch2)); __ bind(&strings_not_equal); - ASSERT(is_int16(NOT_EQUAL)); + DCHECK(is_int16(NOT_EQUAL)); __ Ret(USE_DELAY_SLOT); __ li(v0, Operand(Smi::FromInt(NOT_EQUAL))); @@ -3860,7 +3710,7 @@ void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, __ bind(&check_zero_length); STATIC_ASSERT(kSmiTag == 0); __ Branch(&compare_chars, ne, length, Operand(zero_reg)); - ASSERT(is_int16(EQUAL)); + DCHECK(is_int16(EQUAL)); __ Ret(USE_DELAY_SLOT); __ li(v0, Operand(Smi::FromInt(EQUAL))); @@ -3903,7 +3753,7 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, // Compare lengths - strings up to min-length are equal. __ bind(&compare_lengths); - ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); + DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); // Use length_delta as result if it's zero. __ mov(scratch2, length_delta); __ mov(scratch4, zero_reg); @@ -3986,7 +3836,7 @@ void StringCompareStub::Generate(MacroAssembler* masm) { GenerateCompareFlatAsciiStrings(masm, a1, a0, a2, a3, t0, t1); __ bind(&runtime); - __ TailCallRuntime(Runtime::kHiddenStringCompare, 2, 1); + __ TailCallRuntime(Runtime::kStringCompare, 2, 1); } @@ -4019,7 +3869,7 @@ void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { void ICCompareStub::GenerateSmis(MacroAssembler* masm) { - ASSERT(state_ == CompareIC::SMI); + DCHECK(state_ == CompareIC::SMI); Label miss; __ Or(a2, a1, a0); __ JumpIfNotSmi(a2, &miss); @@ -4042,7 +3892,7 @@ void ICCompareStub::GenerateSmis(MacroAssembler* masm) { void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { - ASSERT(state_ == CompareIC::NUMBER); + DCHECK(state_ == CompareIC::NUMBER); Label generic_stub; Label unordered, maybe_undefined1, maybe_undefined2; @@ -4095,7 +3945,7 @@ void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { __ BranchF(&fpu_lt, NULL, lt, f0, f2); // Otherwise it's greater, so just fall thru, and return. - ASSERT(is_int16(GREATER) && is_int16(EQUAL) && is_int16(LESS)); + DCHECK(is_int16(GREATER) && is_int16(EQUAL) && is_int16(LESS)); __ Ret(USE_DELAY_SLOT); __ li(v0, Operand(GREATER)); @@ -4135,7 +3985,7 @@ void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { - ASSERT(state_ == CompareIC::INTERNALIZED_STRING); + DCHECK(state_ == CompareIC::INTERNALIZED_STRING); Label miss; // Registers containing left and right operands respectively. @@ -4159,13 +4009,13 @@ void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { // Make sure a0 is non-zero. At this point input operands are // guaranteed to be non-zero. - ASSERT(right.is(a0)); + DCHECK(right.is(a0)); STATIC_ASSERT(EQUAL == 0); STATIC_ASSERT(kSmiTag == 0); __ mov(v0, right); // Internalized strings are compared by identity. __ Ret(ne, left, Operand(right)); - ASSERT(is_int16(EQUAL)); + DCHECK(is_int16(EQUAL)); __ Ret(USE_DELAY_SLOT); __ li(v0, Operand(Smi::FromInt(EQUAL))); @@ -4175,8 +4025,8 @@ void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { - ASSERT(state_ == CompareIC::UNIQUE_NAME); - ASSERT(GetCondition() == eq); + DCHECK(state_ == CompareIC::UNIQUE_NAME); + DCHECK(GetCondition() == eq); Label miss; // Registers containing left and right operands respectively. @@ -4206,7 +4056,7 @@ void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { __ Branch(&done, ne, left, Operand(right)); // Make sure a0 is non-zero. At this point input operands are // guaranteed to be non-zero. - ASSERT(right.is(a0)); + DCHECK(right.is(a0)); STATIC_ASSERT(EQUAL == 0); STATIC_ASSERT(kSmiTag == 0); __ li(v0, Operand(Smi::FromInt(EQUAL))); @@ -4219,7 +4069,7 @@ void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { void ICCompareStub::GenerateStrings(MacroAssembler* masm) { - ASSERT(state_ == CompareIC::STRING); + DCHECK(state_ == CompareIC::STRING); Label miss; bool equality = Token::IsEqualityOp(op_); @@ -4262,7 +4112,7 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) { // because we already know they are not identical. We know they are both // strings. if (equality) { - ASSERT(GetCondition() == eq); + DCHECK(GetCondition() == eq); STATIC_ASSERT(kInternalizedTag == 0); __ Or(tmp3, tmp1, Operand(tmp2)); __ And(tmp5, tmp3, Operand(kIsNotInternalizedMask)); @@ -4270,7 +4120,7 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) { __ Branch(&is_symbol, ne, tmp5, Operand(zero_reg)); // Make sure a0 is non-zero. At this point input operands are // guaranteed to be non-zero. - ASSERT(right.is(a0)); + DCHECK(right.is(a0)); __ Ret(USE_DELAY_SLOT); __ mov(v0, a0); // In the delay slot. __ bind(&is_symbol); @@ -4296,7 +4146,7 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) { if (equality) { __ TailCallRuntime(Runtime::kStringEquals, 2, 1); } else { - __ TailCallRuntime(Runtime::kHiddenStringCompare, 2, 1); + __ TailCallRuntime(Runtime::kStringCompare, 2, 1); } __ bind(&miss); @@ -4305,7 +4155,7 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) { void ICCompareStub::GenerateObjects(MacroAssembler* masm) { - ASSERT(state_ == CompareIC::OBJECT); + DCHECK(state_ == CompareIC::OBJECT); Label miss; __ And(a2, a1, Operand(a0)); __ JumpIfSmi(a2, &miss); @@ -4315,7 +4165,7 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { __ GetObjectType(a1, a2, a2); __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); - ASSERT(GetCondition() == eq); + DCHECK(GetCondition() == eq); __ Ret(USE_DELAY_SLOT); __ subu(v0, a0, a1); @@ -4404,7 +4254,7 @@ void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, Register properties, Handle<Name> name, Register scratch0) { - ASSERT(name->IsUniqueName()); + DCHECK(name->IsUniqueName()); // If names of slots in range from 1 to kProbes - 1 for the hash value are // not equal to the name and kProbes-th slot is not used (its name is the // undefined value), it guarantees the hash table doesn't contain the @@ -4421,19 +4271,19 @@ void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i)))); // Scale the index by multiplying by the entry size. - ASSERT(NameDictionary::kEntrySize == 3); + DCHECK(NameDictionary::kEntrySize == 3); __ sll(at, index, 1); __ Addu(index, index, at); Register entity_name = scratch0; // Having undefined at this place means the name is not contained. - ASSERT_EQ(kSmiTagSize, 1); + DCHECK_EQ(kSmiTagSize, 1); Register tmp = properties; __ sll(scratch0, index, 1); __ Addu(tmp, properties, scratch0); __ lw(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); - ASSERT(!tmp.is(entity_name)); + DCHECK(!tmp.is(entity_name)); __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); __ Branch(done, eq, entity_name, Operand(tmp)); @@ -4486,10 +4336,10 @@ void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, Register name, Register scratch1, Register scratch2) { - ASSERT(!elements.is(scratch1)); - ASSERT(!elements.is(scratch2)); - ASSERT(!name.is(scratch1)); - ASSERT(!name.is(scratch2)); + DCHECK(!elements.is(scratch1)); + DCHECK(!elements.is(scratch2)); + DCHECK(!name.is(scratch1)); + DCHECK(!name.is(scratch2)); __ AssertName(name); @@ -4508,7 +4358,7 @@ void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, // Add the probe offset (i + i * i) left shifted to avoid right shifting // the hash in a separate instruction. The value hash + i + i * i is right // shifted in the following and instruction. - ASSERT(NameDictionary::GetProbeOffset(i) < + DCHECK(NameDictionary::GetProbeOffset(i) < 1 << (32 - Name::kHashFieldOffset)); __ Addu(scratch2, scratch2, Operand( NameDictionary::GetProbeOffset(i) << Name::kHashShift)); @@ -4517,7 +4367,7 @@ void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, __ And(scratch2, scratch1, scratch2); // Scale the index by multiplying by the element size. - ASSERT(NameDictionary::kEntrySize == 3); + DCHECK(NameDictionary::kEntrySize == 3); // scratch2 = scratch2 * 3. __ sll(at, scratch2, 1); @@ -4537,7 +4387,7 @@ void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, __ MultiPush(spill_mask); if (name.is(a0)) { - ASSERT(!elements.is(a1)); + DCHECK(!elements.is(a1)); __ Move(a1, name); __ Move(a0, elements); } else { @@ -4593,7 +4443,7 @@ void NameDictionaryLookupStub::Generate(MacroAssembler* masm) { // Add the probe offset (i + i * i) left shifted to avoid right shifting // the hash in a separate instruction. The value hash + i + i * i is right // shifted in the following and instruction. - ASSERT(NameDictionary::GetProbeOffset(i) < + DCHECK(NameDictionary::GetProbeOffset(i) < 1 << (32 - Name::kHashFieldOffset)); __ Addu(index, hash, Operand( NameDictionary::GetProbeOffset(i) << Name::kHashShift)); @@ -4604,14 +4454,14 @@ void NameDictionaryLookupStub::Generate(MacroAssembler* masm) { __ And(index, mask, index); // Scale the index by multiplying by the entry size. - ASSERT(NameDictionary::kEntrySize == 3); + DCHECK(NameDictionary::kEntrySize == 3); // index *= 3. __ mov(at, index); __ sll(index, index, 1); __ Addu(index, index, at); - ASSERT_EQ(kSmiTagSize, 1); + DCHECK_EQ(kSmiTagSize, 1); __ sll(index, index, 2); __ Addu(index, index, dictionary); __ lw(entry_key, FieldMemOperand(index, kElementsStartOffset)); @@ -4660,11 +4510,6 @@ void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( } -bool CodeStub::CanUseFPRegisters() { - return true; // FPU is a base requirement for V8. -} - - // Takes the input in 3 registers: address_ value_ and object_. A pointer to // the value has just been written into the object, now this stub makes sure // we keep the GC informed. The word in the object where the value has been @@ -4753,8 +4598,8 @@ void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { __ PrepareCallCFunction(argument_count, regs_.scratch0()); Register address = a0.is(regs_.address()) ? regs_.scratch0() : regs_.address(); - ASSERT(!address.is(regs_.object())); - ASSERT(!address.is(a0)); + DCHECK(!address.is(regs_.object())); + DCHECK(!address.is(a0)); __ Move(address, regs_.address()); __ Move(a0, regs_.object()); __ Move(a1, address); @@ -4922,7 +4767,7 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { - CEntryStub ces(isolate(), 1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); + CEntryStub ces(isolate(), 1, kSaveFPRegs); __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); int parameter_count_offset = StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; @@ -4975,7 +4820,7 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) { int frame_alignment = masm->ActivationFrameAlignment(); if (frame_alignment > kPointerSize) { __ mov(s5, sp); - ASSERT(IsPowerOf2(frame_alignment)); + DCHECK(IsPowerOf2(frame_alignment)); __ And(sp, sp, Operand(-frame_alignment)); } __ Subu(sp, sp, kCArgsSlotsSize); @@ -5042,12 +4887,12 @@ static void CreateArrayDispatchOneArgument(MacroAssembler* masm, // sp[0] - last argument Label normal_sequence; if (mode == DONT_OVERRIDE) { - ASSERT(FAST_SMI_ELEMENTS == 0); - ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); - ASSERT(FAST_ELEMENTS == 2); - ASSERT(FAST_HOLEY_ELEMENTS == 3); - ASSERT(FAST_DOUBLE_ELEMENTS == 4); - ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); + DCHECK(FAST_SMI_ELEMENTS == 0); + DCHECK(FAST_HOLEY_SMI_ELEMENTS == 1); + DCHECK(FAST_ELEMENTS == 2); + DCHECK(FAST_HOLEY_ELEMENTS == 3); + DCHECK(FAST_DOUBLE_ELEMENTS == 4); + DCHECK(FAST_HOLEY_DOUBLE_ELEMENTS == 5); // is the low bit set? If so, we are holey and that is good. __ And(at, a3, Operand(1)); @@ -5274,7 +5119,7 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { // but the following bit field extraction takes care of that anyway. __ lbu(a3, FieldMemOperand(a3, Map::kBitField2Offset)); // Retrieve elements_kind from bit field 2. - __ Ext(a3, a3, Map::kElementsKindShift, Map::kElementsKindBitCount); + __ DecodeField<Map::ElementsKindBits>(a3); if (FLAG_debug_code) { Label done; @@ -5355,7 +5200,7 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) { FrameScope frame_scope(masm, StackFrame::MANUAL); __ EnterExitFrame(false, kApiStackSpace); - ASSERT(!api_function_address.is(a0) && !scratch.is(a0)); + DCHECK(!api_function_address.is(a0) && !scratch.is(a0)); // a0 = FunctionCallbackInfo& // Arguments is after the return address. __ Addu(a0, sp, Operand(1 * kPointerSize)); |