112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Copyright 2012 the V8 project authors. All rights reserved. 212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be 312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// found in the LICENSE file. 412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/v8.h" 612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#if V8_TARGET_ARCH_MIPS64 812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/bootstrapper.h" 1012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/code-stubs.h" 1112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/codegen.h" 126474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#include "src/ic/handler-compiler.h" 13d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org#include "src/ic/ic.h" 146474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#include "src/isolate.h" 156474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#include "src/jsregexp.h" 1612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/regexp-macro-assembler.h" 176474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#include "src/runtime.h" 1812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgnamespace v8 { 2012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgnamespace internal { 2112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 2212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 2312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void InitializeArrayConstructorDescriptor( 24e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org Isolate* isolate, CodeStubDescriptor* descriptor, 2512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int constant_stack_parameter_count) { 2612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Address deopt_handler = Runtime::FunctionForId( 2712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Runtime::kArrayConstructor)->entry; 2812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 2912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (constant_stack_parameter_count == 0) { 30e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org descriptor->Initialize(deopt_handler, constant_stack_parameter_count, 3112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org JS_FUNCTION_STUB_MODE); 3212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 33e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org descriptor->Initialize(a0, deopt_handler, constant_stack_parameter_count, 347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); 3512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 3612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 3712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 3812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 3912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void InitializeInternalArrayConstructorDescriptor( 40e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org Isolate* isolate, CodeStubDescriptor* descriptor, 4112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int constant_stack_parameter_count) { 4212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Address deopt_handler = Runtime::FunctionForId( 4312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Runtime::kInternalArrayConstructor)->entry; 4412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 4512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (constant_stack_parameter_count == 0) { 46e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org descriptor->Initialize(deopt_handler, constant_stack_parameter_count, 4712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org JS_FUNCTION_STUB_MODE); 4812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 49e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org descriptor->Initialize(a0, deopt_handler, constant_stack_parameter_count, 507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); 5112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 5212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 5312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 5412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 55e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.orgvoid ArrayNoArgumentConstructorStub::InitializeDescriptor( 56e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org CodeStubDescriptor* descriptor) { 57e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org InitializeArrayConstructorDescriptor(isolate(), descriptor, 0); 5812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 5912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 6012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 61e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.orgvoid ArraySingleArgumentConstructorStub::InitializeDescriptor( 62e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org CodeStubDescriptor* descriptor) { 63e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org InitializeArrayConstructorDescriptor(isolate(), descriptor, 1); 6412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 6512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 6612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 67e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.orgvoid ArrayNArgumentsConstructorStub::InitializeDescriptor( 68e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org CodeStubDescriptor* descriptor) { 69e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org InitializeArrayConstructorDescriptor(isolate(), descriptor, -1); 7012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 7112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 7212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 73e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.orgvoid InternalArrayNoArgumentConstructorStub::InitializeDescriptor( 74e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org CodeStubDescriptor* descriptor) { 75e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0); 7612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 7712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 7812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 79e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.orgvoid InternalArraySingleArgumentConstructorStub::InitializeDescriptor( 80e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org CodeStubDescriptor* descriptor) { 81e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1); 8212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 8312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 8412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 85e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.orgvoid InternalArrayNArgumentsConstructorStub::InitializeDescriptor( 86e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org CodeStubDescriptor* descriptor) { 87e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1); 8812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 8912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 9012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 9112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define __ ACCESS_MASM(masm) 9212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 9312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 9412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, 9512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* slow, 9612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Condition cc); 9712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, 9812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register lhs, 9912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register rhs, 10012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* rhs_not_nan, 10112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* slow, 10212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool strict); 10312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, 10412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register lhs, 10512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register rhs); 10612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 10712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 108e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.orgvoid HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm, 109e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org ExternalReference miss) { 11012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Update the static counter each time a new code stub is generated. 11112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate()->counters()->code_stubs()->Increment(); 11212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 113e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor(); 11442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org int param_count = descriptor.GetEnvironmentParameterCount(); 11512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 11612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Call the runtime system in a fresh internal frame. 11712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 118e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((param_count == 0) || 11942ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org a0.is(descriptor.GetEnvironmentParameterRegister(param_count - 1))); 12012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Push arguments, adjust sp. 12112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(sp, sp, Operand(param_count * kPointerSize)); 12212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 0; i < param_count; ++i) { 12312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Store argument to stack. 12442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org __ sd(descriptor.GetEnvironmentParameterRegister(i), 12542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org MemOperand(sp, (param_count - 1 - i) * kPointerSize)); 12612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 127c74571bbdc0f4a89aeaeba038b6948608e7b3ce5akos.palfi@imgtec.com __ CallExternalReference(miss, param_count); 12812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 12912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 13012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 13112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 13212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 13312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 13412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid DoubleToIStub::Generate(MacroAssembler* masm) { 13512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label out_of_range, only_low, negate, done; 13612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register input_reg = source(); 13712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register result_reg = destination(); 13812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 13912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int double_offset = offset(); 14012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Account for saved regs if input is sp. 14112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (input_reg.is(sp)) double_offset += 3 * kPointerSize; 14212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 14312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register scratch = 14412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GetRegisterThatIsNotOneOf(input_reg, result_reg); 14512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register scratch2 = 14612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch); 14712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register scratch3 = 14812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch2); 14912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DoubleRegister double_scratch = kLithiumScratchDouble; 15012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 15112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(scratch, scratch2, scratch3); 15212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!skip_fastpath()) { 15312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load double input. 15412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ldc1(double_scratch, MemOperand(input_reg, double_offset)); 15512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 15612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Clear cumulative exception flags and save the FCSR. 15712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ cfc1(scratch2, FCSR); 15812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ctc1(zero_reg, FCSR); 15912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 16012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Try a conversion to a signed integer. 16112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Trunc_w_d(double_scratch, double_scratch); 16212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Move the converted value into the result register. 16312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mfc1(scratch3, double_scratch); 16412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 16512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Retrieve and restore the FCSR. 16612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ cfc1(scratch, FCSR); 16712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ctc1(scratch2, FCSR); 16812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 16912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check for overflow and NaNs. 17012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And( 17112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org scratch, scratch, 17212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kFCSROverflowFlagMask | kFCSRUnderflowFlagMask 17312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org | kFCSRInvalidOpFlagMask); 17412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If we had no exceptions then set result_reg and we are done. 17512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label error; 17612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&error, ne, scratch, Operand(zero_reg)); 17712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(result_reg, scratch3); 17812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&done); 17912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&error); 18012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 18112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 18212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load the double value and perform a manual truncation. 18312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register input_high = scratch2; 18412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register input_low = scratch3; 18512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 18612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lw(input_low, MemOperand(input_reg, double_offset)); 18712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lw(input_high, MemOperand(input_reg, double_offset + kIntSize)); 18812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 18912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label normal_exponent, restore_sign; 19012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Extract the biased exponent in result. 19112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ext(result_reg, 19212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org input_high, 19312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org HeapNumber::kExponentShift, 19412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org HeapNumber::kExponentBits); 19512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 19612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check for Infinity and NaNs, which should return 0. 19712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Subu(scratch, result_reg, HeapNumber::kExponentMask); 19812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Movz(result_reg, zero_reg, scratch); 19912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&done, eq, scratch, Operand(zero_reg)); 20012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 20112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Express exponent as delta to (number of mantissa bits + 31). 20212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Subu(result_reg, 20312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org result_reg, 20412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31)); 20512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 20612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If the delta is strictly positive, all bits would be shifted away, 20712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // which means that we can return 0. 20812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&normal_exponent, le, result_reg, Operand(zero_reg)); 20912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(result_reg, zero_reg); 21012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&done); 21112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 21212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&normal_exponent); 21312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1; 21412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Calculate shift. 21512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Addu(scratch, result_reg, Operand(kShiftBase + HeapNumber::kMantissaBits)); 21612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 21712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Save the sign. 21812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register sign = result_reg; 21912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org result_reg = no_reg; 22012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(sign, input_high, Operand(HeapNumber::kSignMask)); 22112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 22212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // On ARM shifts > 31 bits are valid and will result in zero. On MIPS we need 22312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // to check for this specific case. 22412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label high_shift_needed, high_shift_done; 22512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&high_shift_needed, lt, scratch, Operand(32)); 22612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(input_high, zero_reg); 22712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&high_shift_done); 22812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&high_shift_needed); 22912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 23012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set the implicit 1 before the mantissa part in input_high. 23112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Or(input_high, 23212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org input_high, 23312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(1 << HeapNumber::kMantissaBitsInTopWord)); 23412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Shift the mantissa bits to the correct position. 23512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We don't need to clear non-mantissa bits as they will be shifted away. 23612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If they weren't, it would mean that the answer is in the 32bit range. 23712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sllv(input_high, input_high, scratch); 23812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 23912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&high_shift_done); 24012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 24112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Replace the shifted bits with bits from the lower mantissa word. 24212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label pos_shift, shift_done; 24312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(at, 32); 24412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ subu(scratch, at, scratch); 24512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&pos_shift, ge, scratch, Operand(zero_reg)); 24612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 24712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Negate scratch. 24812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Subu(scratch, zero_reg, scratch); 24912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sllv(input_low, input_low, scratch); 25012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&shift_done); 25112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 25212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&pos_shift); 25312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ srlv(input_low, input_low, scratch); 25412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 25512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&shift_done); 25612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Or(input_high, input_high, Operand(input_low)); 25712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Restore sign if necessary. 25812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(scratch, sign); 25912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org result_reg = sign; 26012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sign = no_reg; 26112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Subu(result_reg, zero_reg, input_high); 26212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Movz(result_reg, input_high, scratch); 26312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 26412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&done); 26512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 26612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Pop(scratch, scratch2, scratch3); 26712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 26812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 26912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 27012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 27112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime( 27212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Isolate* isolate) { 27312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org WriteInt32ToHeapNumberStub stub1(isolate, a1, v0, a2, a3); 27412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org WriteInt32ToHeapNumberStub stub2(isolate, a2, v0, a3, a0); 27512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stub1.GetCode(); 27612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stub2.GetCode(); 27712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 27812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 27912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 28012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// See comment for class, this does NOT work for int32's that are in Smi range. 28112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { 28212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label max_negative_int; 28312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the_int_ has the answer which is a signed int32 but not a Smi. 28412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We test for the special value that has a different exponent. 28512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); 28612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Test sign, and save for later conditionals. 2879aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ And(sign(), the_int(), Operand(0x80000000u)); 2889aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ Branch(&max_negative_int, eq, the_int(), Operand(0x80000000u)); 28912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 29012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up the correct exponent in scratch_. All non-Smi int32s have the same. 29112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). 29212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t non_smi_exponent = 29312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; 2949aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ li(scratch(), Operand(non_smi_exponent)); 29512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set the sign bit in scratch_ if the value was negative. 2969aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ or_(scratch(), scratch(), sign()); 29712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Subtract from 0 if the value was negative. 2989aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ subu(at, zero_reg, the_int()); 2999aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ Movn(the_int(), at, sign()); 30012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We should be masking the implict first digit of the mantissa away here, 30112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // but it just ends up combining harmlessly with the last digit of the 30212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get 30312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the most significant 1 to hit the last bit of the 12 bit sign and exponent. 304e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); 30512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; 3069aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ srl(at, the_int(), shift_distance); 3079aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ or_(scratch(), scratch(), at); 3089aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ sw(scratch(), FieldMemOperand(the_heap_number(), 30912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org HeapNumber::kExponentOffset)); 3109aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ sll(scratch(), the_int(), 32 - shift_distance); 31112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 3129aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ sw(scratch(), FieldMemOperand(the_heap_number(), 31312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org HeapNumber::kMantissaOffset)); 31412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 31512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&max_negative_int); 31612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The max negative int32 is stored as a positive number in the mantissa of 31712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a double because it uses a sign bit instead of using two's complement. 31812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The actual mantissa bits stored are all 0 because the implicit most 31912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // significant 1 bit is not stored. 32012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org non_smi_exponent += 1 << HeapNumber::kExponentShift; 3219aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ li(scratch(), Operand(HeapNumber::kSignMask | non_smi_exponent)); 3229aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ sw(scratch(), 3239aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org FieldMemOperand(the_heap_number(), HeapNumber::kExponentOffset)); 3249aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ mov(scratch(), zero_reg); 32512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 3269aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ sw(scratch(), 3279aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org FieldMemOperand(the_heap_number(), HeapNumber::kMantissaOffset)); 32812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 32912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 33012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 33112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Handle the case where the lhs and rhs are the same object. 33212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Equality is almost reflexive (everything but NaN), so this is a test 33312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// for "identity and not NaN". 33412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, 33512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* slow, 33612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Condition cc) { 33712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label not_identical; 33812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label heap_number, return_equal; 33912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register exp_mask_reg = t1; 34012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 34112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(¬_identical, ne, a0, Operand(a1)); 34212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 34312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(exp_mask_reg, Operand(HeapNumber::kExponentMask)); 34412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 34512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), 34612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // so we do the second best thing - test it ourselves. 34712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // They are both equal and they are not both Smis so both of them are not 34812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Smis. If it's not a heap number, then return equal. 34912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc == less || cc == greater) { 35012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a0, t0, t0); 35112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(slow, greater, t0, Operand(FIRST_SPEC_OBJECT_TYPE)); 35212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 35312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a0, t0, t0); 35412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&heap_number, eq, t0, Operand(HEAP_NUMBER_TYPE)); 35512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Comparing JS objects with <=, >= is complicated. 35612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc != eq) { 35712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(slow, greater, t0, Operand(FIRST_SPEC_OBJECT_TYPE)); 35812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Normally here we fall through to return_equal, but undefined is 35912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // special: (undefined == undefined) == true, but 36012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (undefined <= undefined) == false! See ECMAScript 11.8.5. 36112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc == less_equal || cc == greater_equal) { 36212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&return_equal, ne, t0, Operand(ODDBALL_TYPE)); 36312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a6, Heap::kUndefinedValueRootIndex); 36412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&return_equal, ne, a0, Operand(a6)); 365e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(is_int16(GREATER) && is_int16(LESS)); 36612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 36712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc == le) { 36812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // undefined <= undefined should fail. 36912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(GREATER)); 37012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 37112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // undefined >= undefined should fail. 37212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(LESS)); 37312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 37412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 37512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 37612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 37712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 37812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&return_equal); 379e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(is_int16(GREATER) && is_int16(LESS)); 38012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 38112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc == less) { 38212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(GREATER)); // Things aren't less than themselves. 38312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (cc == greater) { 38412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(LESS)); // Things aren't greater than themselves. 38512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 38612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, zero_reg); // Things are <=, >=, ==, === themselves. 38712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 38812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // For less and greater we don't have to check for NaN since the result of 38912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // x < x is false regardless. For the others here is some code to check 39012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // for NaN. 39112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc != lt && cc != gt) { 39212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&heap_number); 39312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // It is a heap number, so return non-equal if it's NaN and equal if it's 39412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // not NaN. 39512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 39612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The representation of NaN values has all exponent bits (52..62) set, 39712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // and not all mantissa bits (0..51) clear. 39812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Read top bits of double representation (second word of value). 39912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lwu(a6, FieldMemOperand(a0, HeapNumber::kExponentOffset)); 40012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Test that exponent bits are all set. 40112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a7, a6, Operand(exp_mask_reg)); 40212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If all bits not set (ne cond), then not a NaN, objects are equal. 40312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&return_equal, ne, a7, Operand(exp_mask_reg)); 40412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 40512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Shift out flag and all exponent bits, retaining only mantissa. 40612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sll(a6, a6, HeapNumber::kNonMantissaBitsInTopWord); 40712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Or with all low-bits of mantissa. 40812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lwu(a7, FieldMemOperand(a0, HeapNumber::kMantissaOffset)); 40912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Or(v0, a7, Operand(a6)); 41012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // For equal we already have the right value in v0: Return zero (equal) 41112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // if all bits in mantissa are zero (it's an Infinity) and non-zero if 41212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // not (it's a NaN). For <= and >= we need to load v0 with the failing 41312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // value if it's a NaN. 41412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc != eq) { 41512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // All-zero means Infinity means equal. 41612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(eq, v0, Operand(zero_reg)); 417e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(is_int16(GREATER) && is_int16(LESS)); 41812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 41912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc == le) { 42012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(GREATER)); // NaN <= NaN should fail. 42112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 42212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(LESS)); // NaN >= NaN should fail. 42312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 42412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 42512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 42612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // No fall through here. 42712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 42812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_identical); 42912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 43012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 43112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 43212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, 43312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register lhs, 43412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register rhs, 43512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* both_loaded_as_doubles, 43612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* slow, 43712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool strict) { 438e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((lhs.is(a0) && rhs.is(a1)) || 43912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (lhs.is(a1) && rhs.is(a0))); 44012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 44112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label lhs_is_smi; 44212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(lhs, &lhs_is_smi); 44312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Rhs is a Smi. 44412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check whether the non-smi is a heap number. 44512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(lhs, t0, t0); 44612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strict) { 44712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If lhs was not a number and rhs was a Smi then strict equality cannot 44812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // succeed. Return non-equal (lhs is already not zero). 44912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT, ne, t0, Operand(HEAP_NUMBER_TYPE)); 45012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, lhs); 45112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 45212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Smi compared non-strictly with a non-Smi non-heap-number. Call 45312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the runtime. 45412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(slow, ne, t0, Operand(HEAP_NUMBER_TYPE)); 45512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 45612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Rhs is a smi, lhs is a number. 45712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Convert smi rhs to double. 45812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(at, rhs); 45912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mtc1(at, f14); 46012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ cvt_d_w(f14, f14); 46112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 46212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 46312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We now have both loaded as doubles. 46412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(both_loaded_as_doubles); 46512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 46612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&lhs_is_smi); 46712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Lhs is a Smi. Check whether the non-smi is a heap number. 46812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(rhs, t0, t0); 46912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strict) { 47012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If lhs was not a number and rhs was a Smi then strict equality cannot 47112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // succeed. Return non-equal. 47212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT, ne, t0, Operand(HEAP_NUMBER_TYPE)); 47312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(1)); 47412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 47512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Smi compared non-strictly with a non-Smi non-heap-number. Call 47612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the runtime. 47712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(slow, ne, t0, Operand(HEAP_NUMBER_TYPE)); 47812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 47912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 48012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Lhs is a smi, rhs is a number. 48112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Convert smi lhs to double. 48212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(at, lhs); 48312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mtc1(at, f12); 48412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ cvt_d_w(f12, f12); 48512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 48612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Fall through to both_loaded_as_doubles. 48712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 48812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 48912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 49012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, 49112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register lhs, 49212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register rhs) { 49312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If either operand is a JS object or an oddball value, then they are 49412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // not equal since their pointers are different. 49512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // There is no test for undetectability in strict equality. 49612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); 49712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label first_non_object; 49812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the type of the first operand into a2 and compare it with 49912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // FIRST_SPEC_OBJECT_TYPE. 50012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(lhs, a2, a2); 50112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&first_non_object, less, a2, Operand(FIRST_SPEC_OBJECT_TYPE)); 50212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 50312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Return non-zero. 50412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label return_not_equal; 50512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&return_not_equal); 50612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 50712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(1)); 50812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 50912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&first_non_object); 51012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check for oddballs: true, false, null, undefined. 51112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&return_not_equal, eq, a2, Operand(ODDBALL_TYPE)); 51212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 51312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(rhs, a3, a3); 51412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&return_not_equal, greater, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); 51512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 51612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check for oddballs: true, false, null, undefined. 51712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&return_not_equal, eq, a3, Operand(ODDBALL_TYPE)); 51812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 51912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Now that we have the types we might as well check for 52012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // internalized-internalized. 52112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 52212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Or(a2, a2, Operand(a3)); 52312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a2, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 52412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&return_not_equal, eq, at, Operand(zero_reg)); 52512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 52612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 52712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 52812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, 52912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register lhs, 53012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register rhs, 53112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* both_loaded_as_doubles, 53212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* not_heap_numbers, 53312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* slow) { 53412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(lhs, a3, a2); 53512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(not_heap_numbers, ne, a2, Operand(HEAP_NUMBER_TYPE)); 53612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, FieldMemOperand(rhs, HeapObject::kMapOffset)); 53712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If first was a heap number & second wasn't, go to slow case. 53812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(slow, ne, a3, Operand(a2)); 53912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 54012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Both are heap numbers. Load them up then jump to the code we have 54112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // for that. 54212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 54312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 54412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 54512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(both_loaded_as_doubles); 54612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 54712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 54812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 54912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Fast negative check for internalized-to-internalized equality. 55012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, 55112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register lhs, 55212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register rhs, 55312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* possible_strings, 55412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* not_both_strings) { 555e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((lhs.is(a0) && rhs.is(a1)) || 55612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (lhs.is(a1) && rhs.is(a0))); 55712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 55812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2 is object type of rhs. 55912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label object_test; 56012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 56112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a2, Operand(kIsNotStringMask)); 56212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&object_test, ne, at, Operand(zero_reg)); 56312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a2, Operand(kIsNotInternalizedMask)); 56412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(possible_strings, ne, at, Operand(zero_reg)); 56512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(rhs, a3, a3); 56612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(not_both_strings, ge, a3, Operand(FIRST_NONSTRING_TYPE)); 56712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a3, Operand(kIsNotInternalizedMask)); 56812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(possible_strings, ne, at, Operand(zero_reg)); 56912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 57012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Both are internalized strings. We already checked they weren't the same 57112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // pointer so they are not equal. 57212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 57312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(1)); // Non-zero indicates not equal. 57412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 57512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&object_test); 57612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(not_both_strings, lt, a2, Operand(FIRST_SPEC_OBJECT_TYPE)); 57712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(rhs, a2, a3); 57812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(not_both_strings, lt, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); 57912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 58012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If both objects are undetectable, they are equal. Otherwise, they 58112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // are not equal, since they are different objects and an object is not 58212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // equal to undefined. 58312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, FieldMemOperand(lhs, HeapObject::kMapOffset)); 58412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(a2, FieldMemOperand(a2, Map::kBitFieldOffset)); 58512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(a3, FieldMemOperand(a3, Map::kBitFieldOffset)); 58612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ and_(a0, a2, a3); 58712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a0, a0, Operand(1 << Map::kIsUndetectable)); 58812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 58912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ xori(v0, a0, 1 << Map::kIsUndetectable); 59012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 59112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 59212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 5939aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.orgstatic void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, 59412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register scratch, 595d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org CompareICState::State expected, 59612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* fail) { 59712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label ok; 598d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org if (expected == CompareICState::SMI) { 59912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(input, fail); 600d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org } else if (expected == CompareICState::NUMBER) { 60112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(input, &ok); 60212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, 60312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DONT_DO_SMI_CHECK); 60412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 60512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We could be strict about internalized/string here, but as long as 60612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // hydrogen doesn't care, the stub doesn't have to care either. 60712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&ok); 60812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 60912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 61012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 61112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// On entry a1 and a2 are the values to be compared. 61212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// On exit a0 is 0, positive or negative to indicate the result of 61312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// the comparison. 6149aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.orgvoid CompareICStub::GenerateGeneric(MacroAssembler* masm) { 61512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register lhs = a1; 61612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register rhs = a0; 61712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Condition cc = GetCondition(); 61812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 61912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 6209aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org CompareICStub_CheckInputType(masm, lhs, a2, left(), &miss); 6219aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org CompareICStub_CheckInputType(masm, rhs, a3, right(), &miss); 62212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 62312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label slow; // Call builtin. 62412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label not_smis, both_loaded_as_doubles; 62512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 62612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label not_two_smis, smi_done; 62712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Or(a2, a1, a0); 62812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(a2, ¬_two_smis); 62912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a1); 63012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a0); 63112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 63212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 63312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsubu(v0, a1, a0); 63412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_two_smis); 63512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 63612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // NOTICE! This code is only reached after a smi-fast-case check, so 63712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // it is certain that at least one operand isn't a smi. 63812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 63912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Handle the case where the objects are identical. Either returns the answer 64012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // or goes to slow. Only falls through if the objects were not identical. 64112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitIdenticalObjectComparison(masm, &slow, cc); 64212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 64312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If either is a Smi (we know that not both are), then they can only 64412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // be strictly equal if the other is a HeapNumber. 64512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 646e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(0, Smi::FromInt(0)); 64712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a6, lhs, Operand(rhs)); 64812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(a6, ¬_smis, a4); 64912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // One operand is a smi. EmitSmiNonsmiComparison generates code that can: 65012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 1) Return the answer. 65112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 2) Go to slow. 65212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 3) Fall through to both_loaded_as_doubles. 65312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 4) Jump to rhs_not_nan. 65412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // In cases 3 and 4 we have found out we were dealing with a number-number 65512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // comparison and the numbers have been loaded into f12 and f14 as doubles, 65612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // or in GP registers (a0, a1, a2, a3) depending on the presence of the FPU. 65712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitSmiNonsmiComparison(masm, lhs, rhs, 65812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &both_loaded_as_doubles, &slow, strict()); 65912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 66012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&both_loaded_as_doubles); 66112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // f12, f14 are the double representations of the left hand side 66212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // and the right hand side if we have FPU. Otherwise a2, a3 represent 66312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // left hand side and a0, a1 represent right hand side. 66412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 66512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label nan; 66612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a4, Operand(LESS)); 66712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a5, Operand(GREATER)); 66812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a6, Operand(EQUAL)); 66912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 67012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if either rhs or lhs is NaN. 67112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ BranchF(NULL, &nan, eq, f12, f14); 67212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 67312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if LESS condition is satisfied. If true, move conditionally 67412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // result to v0. 675dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (kArchVariant != kMips64r6) { 676dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ c(OLT, D, f12, f14); 677dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ Movt(v0, a4); 678dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // Use previous check to store conditionally to v0 oposite condition 679dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // (GREATER). If rhs is equal to lhs, this will be corrected in next 680dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // check. 681dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ Movf(v0, a5); 682dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // Check if EQUAL condition is satisfied. If true, move conditionally 683dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // result to v0. 684dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ c(EQ, D, f12, f14); 685dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ Movt(v0, a6); 686dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 687dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org Label skip; 688dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ BranchF(USE_DELAY_SLOT, &skip, NULL, lt, f12, f14); 689dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ mov(v0, a4); // Return LESS as result. 690dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org 691dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ BranchF(USE_DELAY_SLOT, &skip, NULL, eq, f12, f14); 692dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ mov(v0, a6); // Return EQUAL as result. 69312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 694dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ mov(v0, a5); // Return GREATER as result. 695dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ bind(&skip); 696dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 69712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 69812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 69912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&nan); 70012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // NaN comparisons always fail. 70112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load whatever we need in v0 to make the comparison fail. 702e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(is_int16(GREATER) && is_int16(LESS)); 70312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 70412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc == lt || cc == le) { 70512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(GREATER)); 70612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 70712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(LESS)); 70812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 70912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 71012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 71112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_smis); 71212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // At this point we know we are dealing with two different objects, 71312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // and neither of them is a Smi. The objects are in lhs_ and rhs_. 71412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strict()) { 71512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This returns non-equal for some object types, or falls through if it 71612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // was not lucky. 71712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitStrictTwoHeapObjectCompare(masm, lhs, rhs); 71812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 71912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 72012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label check_for_internalized_strings; 72112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label flat_string_check; 72212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check for heap-number-heap-number comparison. Can jump to slow case, 72312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // or load both doubles and jump to the code that handles 72412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // that case. If the inputs are not doubles then jumps to 72512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // check_for_internalized_strings. 72612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // In this case a2 will contain the type of lhs_. 72712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitCheckForTwoHeapNumbers(masm, 72812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org lhs, 72912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org rhs, 73012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &both_loaded_as_doubles, 73112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &check_for_internalized_strings, 73212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &flat_string_check); 73312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 73412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&check_for_internalized_strings); 73512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc == eq && !strict()) { 73612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Returns an answer for two internalized strings or two 73712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // detectable objects. 73812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Otherwise jumps to string case or not both strings case. 73912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Assumes that a2 is the type of lhs_ on entry. 74012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitCheckForInternalizedStringsOrObjects( 74112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm, lhs, rhs, &flat_string_check, &slow); 74212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 74312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 7442c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Check for both being sequential one-byte strings, 7452c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // and inline if that is the case. 74612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&flat_string_check); 74712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 7482c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org __ JumpIfNonSmisNotBothSequentialOneByteStrings(lhs, rhs, a2, a3, &slow); 74912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 75012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, a2, 75112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a3); 75212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc == eq) { 7532c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org StringHelper::GenerateFlatOneByteStringEquals(masm, lhs, rhs, a2, a3, a4); 75412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 7552c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org StringHelper::GenerateCompareFlatOneByteStrings(masm, lhs, rhs, a2, a3, a4, 7562c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org a5); 75712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 75812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Never falls through to here. 75912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 76012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&slow); 76112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Prepare for call to builtin. Push object pointers, a0 (lhs) first, 76212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 (rhs) second. 76312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(lhs, rhs); 76412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Figure out which native to call and setup the arguments. 76512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Builtins::JavaScript native; 76612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc == eq) { 76712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; 76812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 76912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org native = Builtins::COMPARE; 77012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int ncr; // NaN compare result. 77112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc == lt || cc == le) { 77212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ncr = GREATER; 77312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 774e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(cc == gt || cc == ge); // Remaining cases. 77512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ncr = LESS; 77612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 77712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand(Smi::FromInt(ncr))); 77812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ push(a0); 77912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 78012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 78112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 78212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // tagged as a small integer. 78312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ InvokeBuiltin(native, JUMP_FUNCTION); 78412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 78512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 78612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateMiss(masm); 78712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 78812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 78912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 79012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid StoreRegistersStateStub::Generate(MacroAssembler* masm) { 79112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(t9, ra); 79212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ pop(ra); 79351e852008f9f67dbdbae7a40b8aa07fe5c76b45fmachenbach@chromium.org __ PushSafepointRegisters(); 79412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Jump(t9); 79512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 79612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 79712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 79812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid RestoreRegistersStateStub::Generate(MacroAssembler* masm) { 79912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(t9, ra); 80012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ pop(ra); 80151e852008f9f67dbdbae7a40b8aa07fe5c76b45fmachenbach@chromium.org __ PopSafepointRegisters(); 80212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Jump(t9); 80312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 80412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 80512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 80612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 80712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We don't allow a GC during a store buffer overflow so there is no need to 80812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // store the registers in any particular way, but we do have to store and 80912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // restore them. 81012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPush(kJSCallerSaved | ra.bit()); 8119aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org if (save_doubles()) { 81212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPushFPU(kCallerSavedFPU); 81312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 81412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int argument_count = 1; 81512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int fp_argument_count = 0; 81612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Register scratch = a1; 81712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 81812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org AllowExternalCallThatCantCauseGC scope(masm); 81912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); 82012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand(ExternalReference::isolate_address(isolate()))); 82112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallCFunction( 82212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::store_buffer_overflow_function(isolate()), 82312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org argument_count); 8249aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org if (save_doubles()) { 82512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPopFPU(kCallerSavedFPU); 82612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 82712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 82812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPop(kJSCallerSaved | ra.bit()); 82912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 83012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 83112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 83212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 83312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MathPowStub::Generate(MacroAssembler* masm) { 83412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Register base = a1; 8356313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org const Register exponent = MathPowTaggedDescriptor::exponent(); 8366313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org DCHECK(exponent.is(a2)); 83712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Register heapnumbermap = a5; 83812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Register heapnumber = v0; 83912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const DoubleRegister double_base = f2; 84012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const DoubleRegister double_exponent = f4; 84112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const DoubleRegister double_result = f0; 84212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const DoubleRegister double_scratch = f6; 84312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const FPURegister single_scratch = f8; 84412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Register scratch = t1; 84512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Register scratch2 = a7; 84612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 84712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label call_runtime, done, int_exponent; 848fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org if (exponent_type() == ON_STACK) { 84912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label base_is_smi, unpack_exponent; 85012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The exponent and base are supplied as arguments on the stack. 85112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This can only happen if the stub is called from non-optimized code. 85212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load input parameters from stack to double registers. 85312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(base, MemOperand(sp, 1 * kPointerSize)); 85412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(exponent, MemOperand(sp, 0 * kPointerSize)); 85512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 85612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); 85712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 85812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); 85912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(scratch, FieldMemOperand(base, JSObject::kMapOffset)); 86012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); 86112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 86212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); 86312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&unpack_exponent); 86412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 86512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&base_is_smi); 86612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mtc1(scratch, single_scratch); 86712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ cvt_d_w(double_base, single_scratch); 86812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&unpack_exponent); 86912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 87012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 87112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 87212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); 87312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); 87412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ldc1(double_exponent, 87512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(exponent, HeapNumber::kValueOffset)); 876fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org } else if (exponent_type() == TAGGED) { 87712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Base is already in double_base. 87812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 87912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 88012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ldc1(double_exponent, 88112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(exponent, HeapNumber::kValueOffset)); 88212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 88312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 884fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org if (exponent_type() != INTEGER) { 88512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label int_exponent_convert; 88612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Detect integer exponents stored as double. 88712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ EmitFPUTruncate(kRoundToMinusInf, 88812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org scratch, 88912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double_exponent, 89012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org at, 89112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double_scratch, 89212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org scratch2, 89312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kCheckForInexactConversion); 89412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // scratch2 == 0 means there was no conversion error. 89512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); 89612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 897fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org if (exponent_type() == ON_STACK) { 89812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Detect square root case. Crankshaft detects constant +/-0.5 at 89912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // compile time and uses DoMathPowHalf instead. We then skip this check 90012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // for non-constant cases of +/-0.5 as these hardly occur. 90112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label not_plus_half; 90212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 90312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Test for 0.5. 90412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(double_scratch, 0.5); 90512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ BranchF(USE_DELAY_SLOT, 90612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ¬_plus_half, 90712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org NULL, 90812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ne, 90912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double_exponent, 91012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double_scratch); 91112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // double_scratch can be overwritten in the delay slot. 91212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Calculates square root of base. Check for the special case of 91312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). 91412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(double_scratch, -V8_INFINITY); 91512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); 91612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ neg_d(double_result, double_scratch); 91712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 91812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Add +0 to convert -0 to +0. 91912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ add_d(double_scratch, double_base, kDoubleRegZero); 92012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sqrt_d(double_result, double_scratch); 92112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&done); 92212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 92312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_plus_half); 92412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(double_scratch, -0.5); 92512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ BranchF(USE_DELAY_SLOT, 92612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &call_runtime, 92712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org NULL, 92812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ne, 92912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double_exponent, 93012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double_scratch); 93112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // double_scratch can be overwritten in the delay slot. 93212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Calculates square root of base. Check for the special case of 93312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). 93412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(double_scratch, -V8_INFINITY); 93512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); 93612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(double_result, kDoubleRegZero); 93712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 93812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Add +0 to convert -0 to +0. 93912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ add_d(double_scratch, double_base, kDoubleRegZero); 94012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(double_result, 1); 94112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sqrt_d(double_scratch, double_scratch); 94212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ div_d(double_result, double_result, double_scratch); 94312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&done); 94412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 94512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 94612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ push(ra); 94712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 94812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org AllowExternalCallThatCantCauseGC scope(masm); 94912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ PrepareCallCFunction(0, 2, scratch2); 95012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MovToFloatParameters(double_base, double_exponent); 95112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallCFunction( 95212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::power_double_double_function(isolate()), 95312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 0, 2); 95412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 95512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ pop(ra); 95612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MovFromFloatResult(double_result); 95712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&done); 95812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 95912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&int_exponent_convert); 96012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 96112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 96212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Calculate power with integer exponent. 96312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&int_exponent); 96412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 96512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get two copies of exponent in the registers scratch and exponent. 966fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org if (exponent_type() == INTEGER) { 96712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(scratch, exponent); 96812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 96912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Exponent has previously been stored into scratch as untagged integer. 97012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(exponent, scratch); 97112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 97212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 97312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov_d(double_scratch, double_base); // Back up base. 97412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(double_result, 1.0); 97512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 97612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get absolute value of exponent. 97712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label positive_exponent; 97812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&positive_exponent, ge, scratch, Operand(zero_reg)); 97912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(scratch, zero_reg, scratch); 98012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&positive_exponent); 98112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 98212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label while_true, no_carry, loop_end; 98312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&while_true); 98412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 98512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(scratch2, scratch, 1); 98612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 98712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&no_carry, eq, scratch2, Operand(zero_reg)); 98812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mul_d(double_result, double_result, double_scratch); 98912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&no_carry); 99012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 99112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsra(scratch, scratch, 1); 99212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 99312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&loop_end, eq, scratch, Operand(zero_reg)); 99412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mul_d(double_scratch, double_scratch, double_scratch); 99512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 99612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&while_true); 99712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 99812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&loop_end); 99912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 100012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&done, ge, exponent, Operand(zero_reg)); 100112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(double_scratch, 1.0); 100212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ div_d(double_result, double_scratch, double_result); 100312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Test whether result is zero. Bail out to check for subnormal result. 100412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. 100512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); 100612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 100712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // double_exponent may not contain the exponent value if the input was a 100812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // smi. We set it with exponent value before bailing out. 100912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mtc1(exponent, single_scratch); 101012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ cvt_d_w(double_exponent, single_scratch); 101112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 101212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Returning or bailing out. 101312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Counters* counters = isolate()->counters(); 1014fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org if (exponent_type() == ON_STACK) { 101512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The arguments are still on the stack. 101612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&call_runtime); 101712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); 101812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 101912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The stub is called from non-optimized code, which expects the result 102012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // as heap number in exponent. 102112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&done); 102212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ AllocateHeapNumber( 102312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); 102412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sdc1(double_result, 102512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); 1026e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(heapnumber.is(v0)); 102712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); 102812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(2); 102912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 103012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ push(ra); 103112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 103212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org AllowExternalCallThatCantCauseGC scope(masm); 103312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ PrepareCallCFunction(0, 2, scratch); 103412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MovToFloatParameters(double_base, double_exponent); 103512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallCFunction( 103612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::power_double_double_function(isolate()), 103712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 0, 2); 103812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 103912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ pop(ra); 104012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MovFromFloatResult(double_result); 104112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 104212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&done); 104312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); 104412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 104512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 104612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 104712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 104812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 104912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool CEntryStub::NeedsImmovableCode() { 105012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return true; 105112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 105212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 105312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 105412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 105512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CEntryStub::GenerateAheadOfTime(isolate); 105612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); 105712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 105812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 105912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 106012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 106112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org BinaryOpICStub::GenerateAheadOfTime(isolate); 106212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org StoreRegistersStateStub::GenerateAheadOfTime(isolate); 106312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org RestoreRegistersStateStub::GenerateAheadOfTime(isolate); 106412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 106512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 106612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 106712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 106851e852008f9f67dbdbae7a40b8aa07fe5c76b45fmachenbach@chromium.orgvoid StoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { 106951e852008f9f67dbdbae7a40b8aa07fe5c76b45fmachenbach@chromium.org StoreRegistersStateStub stub(isolate); 107051e852008f9f67dbdbae7a40b8aa07fe5c76b45fmachenbach@chromium.org stub.GetCode(); 107112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 107212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 107312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 107451e852008f9f67dbdbae7a40b8aa07fe5c76b45fmachenbach@chromium.orgvoid RestoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { 107551e852008f9f67dbdbae7a40b8aa07fe5c76b45fmachenbach@chromium.org RestoreRegistersStateStub stub(isolate); 107651e852008f9f67dbdbae7a40b8aa07fe5c76b45fmachenbach@chromium.org stub.GetCode(); 107712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 107812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 107912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 108012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid CodeStub::GenerateFPStubs(Isolate* isolate) { 10812c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Generate if not already in cache. 108212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SaveFPRegsMode mode = kSaveFPRegs; 10832c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org CEntryStub(isolate, 1, mode).GetCode(); 10842c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org StoreBufferOverflowStub(isolate, mode).GetCode(); 108512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate->set_fp_stubs_generated(true); 108612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 108712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 108812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 108912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 109012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CEntryStub stub(isolate, 1, kDontSaveFPRegs); 109112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stub.GetCode(); 109212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 109312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 109412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 109512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid CEntryStub::Generate(MacroAssembler* masm) { 109612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Called from JavaScript; parameters are on stack as if calling JS function 109712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // s0: number of arguments including receiver 109812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // s1: size of arguments excluding receiver 109912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // s2: pointer to builtin function 110012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // fp: frame pointer (restored after C call) 110112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp: stack pointer (restored as callee's sp after C call) 110212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // cp: current context (C callee-saved) 110312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 110412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ProfileEntryHookStub::MaybeCallEntryHook(masm); 110512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 110612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // NOTE: s0-s2 hold the arguments of this function instead of a0-a2. 110712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The reason for this is that these arguments would need to be saved anyway 110812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // so it's faster to set them up directly. 110912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // See MacroAssembler::PrepareCEntryArgs and PrepareCEntryFunction. 111012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 111112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute the argv pointer in a callee-saved register. 111212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(s1, sp, s1); 111312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 111412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Enter the exit frame that transitions from JavaScript to C++. 111512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FrameScope scope(masm, StackFrame::MANUAL); 11166474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ EnterExitFrame(save_doubles()); 111712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 111812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // s0: number of arguments including receiver (C callee-saved) 111912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // s1: pointer to first argument (C callee-saved) 112012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // s2: pointer to builtin function (C callee-saved) 112112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 112212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Prepare arguments for C routine. 112312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a0 = argc 112412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a0, s0); 112512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 = argv (set in the delay slot after find_ra below). 112612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 112712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We 112812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // also need to reserve the 4 argument slots on the stack. 112912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 113012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ AssertStackIsAligned(); 113112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 113212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a2, Operand(ExternalReference::isolate_address(isolate()))); 113312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 113412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // To let the GC traverse the return address of the exit frames, we need to 113512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // know where the return address is. The CEntryStub is unmovable, so 113612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // we can store the address on the stack to be able to find it again and 113712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // we never have to restore it, because it will not change. 113812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); 113912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This branch-and-link sequence is needed to find the current PC on mips, 114012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // saved to the ra register. 114112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Use masm-> here instead of the double-underscore macro since extra 114212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // coverage code can interfere with the proper calculation of ra. 114312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label find_ra; 114412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->bal(&find_ra); // bal exposes branch delay slot. 114512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->mov(a1, s1); 114612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->bind(&find_ra); 114712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 114812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Adjust the value in ra to point to the correct return location, 2nd 114912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // instruction past the real call into C code (the jalr(t9)), and push it. 115012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This is the return address of the exit frame. 115112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kNumInstructionsToJump = 5; 115212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->Daddu(ra, ra, kNumInstructionsToJump * kInt32Size); 115312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->sd(ra, MemOperand(sp)); // This spot was reserved in EnterExitFrame. 115412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stack space reservation moved to the branch delay slot below. 115512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stack is still aligned. 115612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 115712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Call the C routine. 115812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->mov(t9, s2); // Function pointer to t9 to conform to ABI for PIC. 115912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->jalr(t9); 116012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up sp in the delay slot. 116112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->daddiu(sp, sp, -kCArgsSlotsSize); 116212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Make sure the stored 'ra' points to this position. 1163e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(kNumInstructionsToJump, 116412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->InstructionsGeneratedSince(&find_ra)); 116512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 116612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 116712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Runtime functions should not return 'the hole'. Allowing it to escape may 116812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // lead to crashes in the IC code later. 116912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_debug_code) { 117012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label okay; 117112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); 117212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&okay, ne, v0, Operand(a4)); 117312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ stop("The hole escaped"); 117412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&okay); 117512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 117612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 117712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check result for exception sentinel. 117812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label exception_returned; 117912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a4, Heap::kExceptionRootIndex); 118012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&exception_returned, eq, a4, Operand(v0)); 118112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 118212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference pending_exception_address( 118312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Isolate::kPendingExceptionAddress, isolate()); 118412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 118512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that there is no pending exception, otherwise we 118612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // should have returned the exception sentinel. 118712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_debug_code) { 118812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label okay; 118912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a2, Operand(pending_exception_address)); 119012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, MemOperand(a2)); 119112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); 119212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Cannot use check here as it attempts to generate call into runtime. 119312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&okay, eq, a4, Operand(a2)); 119412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ stop("Unexpected pending exception"); 119512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&okay); 119612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 119712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 119812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Exit C frame and return. 119912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // v0:v1: result 120012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp: stack pointer 120112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // fp: frame pointer 120212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // s0: still holds argc (callee-saved). 12036474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ LeaveExitFrame(save_doubles(), s0, true, EMIT_RETURN); 120412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 120512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Handling of exception. 120612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&exception_returned); 120712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 120812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Retrieve the pending exception. 120912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a2, Operand(pending_exception_address)); 121012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(v0, MemOperand(a2)); 121112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 121212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Clear the pending exception. 121312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a3, Operand(isolate()->factory()->the_hole_value())); 121412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, MemOperand(a2)); 121512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 121612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Special handling of termination exceptions which are uncatchable 121712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // by javascript code. 121812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label throw_termination_exception; 121912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a4, Heap::kTerminationExceptionRootIndex); 122012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&throw_termination_exception, eq, v0, Operand(a4)); 122112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 122212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Handle normal exception. 122312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Throw(v0); 122412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 122512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&throw_termination_exception); 122612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ThrowUncatchable(v0); 122712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 122812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 122912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 123042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.orgvoid JSEntryStub::Generate(MacroAssembler* masm) { 123112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label invoke, handler_entry, exit; 123212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Isolate* isolate = masm->isolate(); 123312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 123412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(plind): unify the ABI description here. 123512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Registers: 123612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a0: entry address 123712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: function 123812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2: receiver 123912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3: argc 124012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a4 (a4): on mips64 124112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 124212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stack: 124312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 0 arg slots on mips64 (4 args slots on mips) 124412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // args -- in a4/a4 on mips64, on stack on mips 124512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 124612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ProfileEntryHookStub::MaybeCallEntryHook(masm); 124712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 124812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Save callee saved registers on the stack. 124912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPush(kCalleeSaved | ra.bit()); 125012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 125112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Save callee-saved FPU registers. 125212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPushFPU(kCalleeSavedFPU); 125312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up the reserved register for 0.0. 125412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(kDoubleRegZero, 0.0); 125512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 125612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load argv in s0 register. 125712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (kMipsAbi == kN64) { 125812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(s0, a4); // 5th parameter in mips64 a4 (a4) register. 125912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { // Abi O32. 126012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 5th parameter on stack for O32 abi. 126112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize; 126212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org offset_to_argv += kNumCalleeSavedFPU * kDoubleSize; 126312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(s0, MemOperand(sp, offset_to_argv + kCArgsSlotsSize)); 126412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 126512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 126612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ InitializeRootRegister(); 126712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 126812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We build an EntryFrame. 126912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a7, Operand(-1)); // Push a bad frame pointer to fail if it is used. 127042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org int marker = type(); 127112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a6, Operand(Smi::FromInt(marker))); 127212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a5, Operand(Smi::FromInt(marker))); 127312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference c_entry_fp(Isolate::kCEntryFPAddress, isolate); 127412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a4, Operand(c_entry_fp)); 127512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, MemOperand(a4)); 127612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(a7, a6, a5, a4); 127712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up frame pointer for the frame to be pushed. 127812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddiu(fp, sp, -EntryFrameConstants::kCallerFPOffset); 127912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 128012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Registers: 128112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a0: entry_address 128212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: function 128312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2: receiver_pointer 128412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3: argc 128512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // s0: argv 128612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 128712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stack: 128812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // caller fp | 128912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // function slot | entry frame 129012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // context slot | 129112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // bad fp (0xff...f) | 129212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // callee saved registers + ra 129312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // [ O32: 4 args slots] 129412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // args 129512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 129612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If this is the outermost JS call, set js_entry_sp value. 129712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label non_outermost_js; 129812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate); 129912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a5, Operand(ExternalReference(js_entry_sp))); 130012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a6, MemOperand(a5)); 130112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&non_outermost_js, ne, a6, Operand(zero_reg)); 130212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(fp, MemOperand(a5)); 130312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a4, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); 130412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label cont; 130512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ b(&cont); 130612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ nop(); // Branch delay slot nop. 130712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&non_outermost_js); 130812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a4, Operand(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME))); 130912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&cont); 131012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ push(a4); 131112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 131212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Jump to a faked try block that does the invoke, with a faked catch 131312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // block that sets the pending exception. 131412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&invoke); 131512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&handler_entry); 131612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org handler_offset_ = handler_entry.pos(); 131712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Caught exception: Store result (exception) in the pending exception 131812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // field in the JSEnv and return a failure sentinel. Coming in here the 131912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // fp will be invalid because the PushTryHandler below sets it to 0 to 132012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // signal the existence of the JSEntry frame. 132112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a4, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 132212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate))); 132312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(v0, MemOperand(a4)); // We come back from 'invoke'. result is in v0. 132412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(v0, Heap::kExceptionRootIndex); 132512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ b(&exit); // b exposes branch delay slot. 132612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ nop(); // Branch delay slot nop. 132712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 132812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Invoke: Link this frame into the handler chain. There's only one 132912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // handler block in this code object, so its index is 0. 133012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&invoke); 133112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ PushTryHandler(StackHandler::JS_ENTRY, 0); 133212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If an exception not caught by another handler occurs, this handler 133312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // returns control to the code after the bal(&invoke) above, which 133412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // restores all kCalleeSaved registers (including cp and fp) to their 133512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // saved values before returning a failure to C. 133612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 133712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Clear any pending exceptions. 133812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a5, Heap::kTheHoleValueRootIndex); 133912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a4, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 134012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate))); 134112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a5, MemOperand(a4)); 134212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 134312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Invoke the function by calling through JS entry trampoline builtin. 134412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Notice that we cannot store a reference to the trampoline code directly in 134512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // this stub, because runtime stubs are not traversed when doing GC. 134612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 134712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Registers: 134812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a0: entry_address 134912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: function 135012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2: receiver_pointer 135112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3: argc 135212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // s0: argv 135312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 135412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stack: 135512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // handler frame 135612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // entry frame 135712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // callee saved registers + ra 135812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // [ O32: 4 args slots] 135912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // args 136012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 136142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org if (type() == StackFrame::ENTRY_CONSTRUCT) { 136212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline, 136312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate); 136412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a4, Operand(construct_entry)); 136512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 136612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference entry(Builtins::kJSEntryTrampoline, masm->isolate()); 136712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a4, Operand(entry)); 136812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 136912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(t9, MemOperand(a4)); // Deref address. 137012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Call JSEntryTrampoline. 137112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddiu(t9, t9, Code::kHeaderSize - kHeapObjectTag); 137212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Call(t9); 137312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 137412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Unlink this frame from the handler chain. 137512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ PopTryHandler(); 137612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 137712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&exit); // v0 holds result 137812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if the current stack frame is marked as the outermost JS frame. 137912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label non_outermost_js_2; 138012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ pop(a5); 138112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&non_outermost_js_2, 138212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ne, 138312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a5, 138412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); 138512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a5, Operand(ExternalReference(js_entry_sp))); 138612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(zero_reg, MemOperand(a5)); 138712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&non_outermost_js_2); 138812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 138912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Restore the top frame descriptors from the stack. 139012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ pop(a5); 139112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a4, Operand(ExternalReference(Isolate::kCEntryFPAddress, 139212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate))); 139312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a5, MemOperand(a4)); 139412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 139512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Reset the stack to the callee saved registers. 139612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddiu(sp, sp, -EntryFrameConstants::kCallerFPOffset); 139712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 139812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Restore callee-saved fpu registers. 139912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPopFPU(kCalleeSavedFPU); 140012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 140112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Restore callee saved registers from the stack. 140212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPop(kCalleeSaved | ra.bit()); 140312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Return. 140412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Jump(ra); 140512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 140612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 140712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 140812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Uses registers a0 to a4. 140912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Expected input (depending on whether args are in registers or on the stack): 141012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// * object: a0 or at sp + 1 * kPointerSize. 141112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// * function: a1 or at sp. 141212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// 141312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// An inlined call site may have been generated before calling this stub. 141412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// In this case the offset to the inline site to patch is passed on the stack, 141512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// in the safepoint slot for register a4. 141612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid InstanceofStub::Generate(MacroAssembler* masm) { 141712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Call site inlining and patching implies arguments in registers. 1418e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(HasArgsInRegisters() || !HasCallSiteInlineCheck()); 141912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ReturnTrueFalse is only implemented for inlined call sites. 1420e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!ReturnTrueFalseObject() || HasCallSiteInlineCheck()); 142112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 142212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Fixed register usage throughout the stub: 142312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Register object = a0; // Object (lhs). 142412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register map = a3; // Map of the object. 142512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Register function = a1; // Function (rhs). 142612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Register prototype = a4; // Prototype of the function. 142712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Register inline_site = t1; 142812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Register scratch = a2; 142912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 143012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int32_t kDeltaToLoadBoolResult = 7 * Assembler::kInstrSize; 143112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 143212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label slow, loop, is_instance, is_not_instance, not_js_object; 143312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 143412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!HasArgsInRegisters()) { 143512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(object, MemOperand(sp, 1 * kPointerSize)); 143612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(function, MemOperand(sp, 0)); 143712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 143812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 143912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the left hand is a JS object and load map. 144012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(object, ¬_js_object); 144112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); 144212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 144312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If there is a call site cache don't look in the global cache, but do the 144412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // real lookup and update the call site cache. 144512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!HasCallSiteInlineCheck()) { 144612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 144712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kInstanceofCacheFunctionRootIndex); 144812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, ne, function, Operand(at)); 144912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kInstanceofCacheMapRootIndex); 145012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, ne, map, Operand(at)); 145112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); 145212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 145312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 145412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 145512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 145612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 145712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the prototype of the function. 145812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); 145912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 146012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the function prototype is a JS object. 146112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(prototype, &slow); 146212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); 146312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 146412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Update the global instanceof or call site inlined cache with the current 146512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // map and function. The cached answer will be set when it is known below. 146612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!HasCallSiteInlineCheck()) { 146712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 146812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); 146912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 1470e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(HasArgsInRegisters()); 147112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Patch the (relocated) inlined map check. 147212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 147312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The offset was stored in a4 safepoint slot. 147412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal). 147512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadFromSafepointRegisterSlot(scratch, a4); 147612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(inline_site, ra, scratch); 147712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the map location in scratch and patch it. 147812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetRelocatedValue(inline_site, scratch, v1); // v1 used as scratch. 147912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(map, FieldMemOperand(scratch, Cell::kValueOffset)); 148012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 148112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 148212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Register mapping: a3 is object map and a4 is function prototype. 148312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get prototype of object into a2. 148412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(scratch, FieldMemOperand(map, Map::kPrototypeOffset)); 148512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 148612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We don't need map any more. Use it as a scratch register. 148712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register scratch2 = map; 148812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org map = no_reg; 148912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 149012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Loop through the prototype chain looking for the function prototype. 149112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(scratch2, Heap::kNullValueRootIndex); 149212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&loop); 149312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&is_instance, eq, scratch, Operand(prototype)); 149412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&is_not_instance, eq, scratch, Operand(scratch2)); 149512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset)); 149612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset)); 149712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&loop); 149812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 149912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&is_instance); 1500e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(Smi::FromInt(0) == 0); 150112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!HasCallSiteInlineCheck()) { 150212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, zero_reg); 150312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); 150412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 150512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Patch the call site to return true. 150612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(v0, Heap::kTrueValueRootIndex); 150712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(inline_site, inline_site, Operand(kDeltaToLoadBoolResult)); 150812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the boolean result location in scratch and patch it. 150912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ PatchRelocatedValue(inline_site, scratch, v0); 151012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 151112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!ReturnTrueFalseObject()) { 1512e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(Smi::FromInt(0), 0); 151312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, zero_reg); 151412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 151512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 151612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 151712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 151812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&is_not_instance); 151912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!HasCallSiteInlineCheck()) { 152012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(1))); 152112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); 152212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 152312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Patch the call site to return false. 152412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(v0, Heap::kFalseValueRootIndex); 152512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(inline_site, inline_site, Operand(kDeltaToLoadBoolResult)); 152612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the boolean result location in scratch and patch it. 152712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ PatchRelocatedValue(inline_site, scratch, v0); 152812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 152912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!ReturnTrueFalseObject()) { 153012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(1))); 153112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 153212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 153312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 153412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 153512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 153612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label object_not_null, object_not_null_or_smi; 153712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_js_object); 153812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Before null, smi and string value checks, check that the rhs is a function 153912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // as for a non-function rhs an exception needs to be thrown. 154012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(function, &slow); 154112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(function, scratch2, scratch); 154212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&slow, ne, scratch, Operand(JS_FUNCTION_TYPE)); 154312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 154412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Null is not instance of anything. 154512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&object_not_null, 154612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ne, 154712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org scratch, 154812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(isolate()->factory()->null_value())); 154912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(1))); 155012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 155112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 155212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&object_not_null); 155312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Smi values are not instances of anything. 155412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(object, &object_not_null_or_smi); 155512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(1))); 155612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 155712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 155812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&object_not_null_or_smi); 155912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // String values are not instances of anything. 156012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ IsObjectJSStringType(object, scratch, &slow); 156112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(1))); 156212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 156312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 156412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Slow-case. Tail call builtin. 156512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&slow); 156612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!ReturnTrueFalseObject()) { 156712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (HasArgsInRegisters()) { 156812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(a0, a1); 156912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 157012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 157112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 157212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 157312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 157412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(a0, a1); 157512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); 157612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 157712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a0, v0); 157812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(v0, Heap::kTrueValueRootIndex); 157912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(HasArgsInRegisters() ? 0 : 2, eq, a0, Operand(zero_reg)); 158012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(v0, Heap::kFalseValueRootIndex); 158112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 158212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 158312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 158412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 158512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 158612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid FunctionPrototypeStub::Generate(MacroAssembler* masm) { 158712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 15889aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org Register receiver = LoadDescriptor::ReceiverRegister(); 1589eb81c479217278e101fc47fd29872a7e68f02402machenbach@chromium.org NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, a3, 1590eb81c479217278e101fc47fd29872a7e68f02402machenbach@chromium.org a4, &miss); 159112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 1592eb81c479217278e101fc47fd29872a7e68f02402machenbach@chromium.org PropertyAccessCompiler::TailCallBuiltin( 1593eb81c479217278e101fc47fd29872a7e68f02402machenbach@chromium.org masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC)); 159412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 159512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 159612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 159712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 159812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The displacement is the offset of the last parameter (if any) 159912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // relative to the frame pointer. 160012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kDisplacement = 160112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org StandardFrameConstants::kCallerSPOffset - kPointerSize; 16026313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org DCHECK(a1.is(ArgumentsAccessReadDescriptor::index())); 16036313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org DCHECK(a0.is(ArgumentsAccessReadDescriptor::parameter_count())); 160412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 160512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the key is a smiGenerateReadElement. 160612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label slow; 160712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(a1, &slow); 160812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 160912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if the calling frame is an arguments adaptor frame. 161012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label adaptor; 161112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 161212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); 161312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&adaptor, 161412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org eq, 161512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a3, 161612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 161712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 161812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check index (a1) against formal parameters count limit passed in 161912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // through register a0. Use unsigned comparison to get negative 162012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // check for free. 162112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&slow, hs, a1, Operand(a0)); 162212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 162312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Read the argument from the stack and return it. 162412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsubu(a3, a0, a1); 162512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(a7, a3, kPointerSizeLog2); 162612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a3, fp, Operand(a7)); 162712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 162812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(v0, MemOperand(a3, kDisplacement)); 162912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 163012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Arguments adaptor case: Check index (a1) against actual arguments 163112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // limit found in the arguments adaptor frame. Use unsigned 163212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // comparison to get negative check for free. 163312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&adaptor); 163412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 163512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&slow, Ugreater_equal, a1, Operand(a0)); 163612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 163712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Read the argument from the adaptor frame and return it. 163812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsubu(a3, a0, a1); 163912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(a7, a3, kPointerSizeLog2); 164012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a3, a2, Operand(a7)); 164112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 164212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(v0, MemOperand(a3, kDisplacement)); 164312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 164412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Slow-case: Handle non-smi or out-of-bounds access to arguments 164512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // by calling the runtime system. 164612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&slow); 164712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ push(a1); 164812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); 164912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 165012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 165112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 165212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { 165312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[0] : number of parameters 165412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[4] : receiver displacement 165512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[8] : function 165612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if the calling frame is an arguments adaptor frame. 165712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label runtime; 165812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 165912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, MemOperand(a3, StandardFrameConstants::kContextOffset)); 166012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, 166112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ne, 166212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a2, 166312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 166412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 166512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Patch the arguments.length and the parameters pointer in the current frame. 166612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset)); 166712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a2, MemOperand(sp, 0 * kPointerSize)); 166812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(a7, a2, kPointerSizeLog2); 166912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a3, a3, Operand(a7)); 167012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddiu(a3, a3, StandardFrameConstants::kCallerSPOffset); 167112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, MemOperand(sp, 1 * kPointerSize)); 167212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 167312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&runtime); 167412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); 167512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 167612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 167712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 167812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { 167912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stack layout: 168012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[0] : number of parameters (tagged) 168112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[4] : address of receiver argument 168212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[8] : function 168312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Registers used over whole function: 168412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a6 : allocated object (tagged) 168512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // t1 : mapped parameter count (tagged) 168612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 168712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a1, MemOperand(sp, 0 * kPointerSize)); 168812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 = parameter count (tagged) 168912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 169012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if the calling frame is an arguments adaptor frame. 169112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label runtime; 169212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label adaptor_frame, try_allocate; 169312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 169412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, MemOperand(a3, StandardFrameConstants::kContextOffset)); 169512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&adaptor_frame, 169612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org eq, 169712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a2, 169812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 169912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 170012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // No adaptor, parameter count = argument count. 170112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a2, a1); 170212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&try_allocate); 170312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 170412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We have an adaptor frame. Patch the parameters pointer. 170512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&adaptor_frame); 170612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset)); 170712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(t2, a2, kPointerSizeLog2); 170812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a3, a3, Operand(t2)); 170912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset)); 171012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, MemOperand(sp, 1 * kPointerSize)); 171112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 171212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 = parameter count (tagged) 171312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2 = argument count (tagged) 171412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute the mapped parameter count = min(a1, a2) in a1. 171512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label skip_min; 171612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&skip_min, lt, a1, Operand(a2)); 171712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a1, a2); 171812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&skip_min); 171912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 172012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&try_allocate); 172112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 172212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute the sizes of backing store, parameter map, and arguments object. 172312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 1. Parameter map, has 2 extra words containing context and backing store. 172412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kParameterMapHeaderSize = 172512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FixedArray::kHeaderSize + 2 * kPointerSize; 172612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If there are no mapped parameters, we do not need the parameter_map. 172712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label param_map_size; 1728e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(0, Smi::FromInt(0)); 172912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(USE_DELAY_SLOT, ¶m_map_size, eq, a1, Operand(zero_reg)); 173012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(t1, zero_reg); // In delay slot: param map size = 0 when a1 == 0. 173112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(t1, a1, kPointerSizeLog2); 173212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddiu(t1, t1, kParameterMapHeaderSize); 173312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¶m_map_size); 173412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 173512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 2. Backing store. 173612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(t2, a2, kPointerSizeLog2); 173712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(t1, t1, Operand(t2)); 173812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(t1, t1, Operand(FixedArray::kHeaderSize)); 173912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 174012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 3. Arguments object. 174112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(t1, t1, Operand(Heap::kSloppyArgumentsObjectSize)); 174212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 174312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Do the allocation of all three objects in one go. 174412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Allocate(t1, v0, a3, a4, &runtime, TAG_OBJECT); 174512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 174612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // v0 = address of new object(s) (tagged) 174712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2 = argument count (smi-tagged) 174812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the arguments boilerplate from the current native context into a4. 174912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kNormalOffset = 175012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); 175112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kAliasedOffset = 175212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX); 175312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 175412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 175512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, FieldMemOperand(a4, GlobalObject::kNativeContextOffset)); 175612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label skip2_ne, skip2_eq; 175712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&skip2_ne, ne, a1, Operand(zero_reg)); 175812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, MemOperand(a4, kNormalOffset)); 175912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&skip2_ne); 176012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 176112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&skip2_eq, eq, a1, Operand(zero_reg)); 176212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, MemOperand(a4, kAliasedOffset)); 176312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&skip2_eq); 176412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 176512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // v0 = address of new object (tagged) 176612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 = mapped parameter count (tagged) 176712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2 = argument count (smi-tagged) 176812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a4 = address of arguments map (tagged) 176912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a4, FieldMemOperand(v0, JSObject::kMapOffset)); 177012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex); 177112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset)); 177212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); 177312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 177412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up the callee in-object property. 177512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); 177612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, MemOperand(sp, 2 * kPointerSize)); 177712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ AssertNotSmi(a3); 177812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kCalleeOffset = JSObject::kHeaderSize + 177912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Heap::kArgumentsCalleeIndex * kPointerSize; 178012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, FieldMemOperand(v0, kCalleeOffset)); 178112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 178212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Use the length (smi tagged) and set that as an in-object property too. 178312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 178412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kLengthOffset = JSObject::kHeaderSize + 178512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Heap::kArgumentsLengthIndex * kPointerSize; 178612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a2, FieldMemOperand(v0, kLengthOffset)); 178712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 178812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up the elements pointer in the allocated arguments object. 178912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If we allocated a parameter map, a4 will point there, otherwise 179012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // it will point to the backing store. 179112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a4, v0, Operand(Heap::kSloppyArgumentsObjectSize)); 179212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset)); 179312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 179412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // v0 = address of new object (tagged) 179512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 = mapped parameter count (tagged) 179612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2 = argument count (tagged) 179712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a4 = address of parameter map or backing store (tagged) 179812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Initialize parameter map. If there are no mapped arguments, we're done. 179912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label skip_parameter_map; 180012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label skip3; 180112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&skip3, ne, a1, Operand(Smi::FromInt(0))); 180212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Move backing store address to a3, because it is 180312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // expected there when filling in the unmapped arguments. 180412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a3, a4); 180512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&skip3); 180612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 180712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&skip_parameter_map, eq, a1, Operand(Smi::FromInt(0))); 180812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 180912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a6, Heap::kSloppyArgumentsElementsMapRootIndex); 181012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a6, FieldMemOperand(a4, FixedArray::kMapOffset)); 181112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a6, a1, Operand(Smi::FromInt(2))); 181212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a6, FieldMemOperand(a4, FixedArray::kLengthOffset)); 181312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(cp, FieldMemOperand(a4, FixedArray::kHeaderSize + 0 * kPointerSize)); 181412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(t2, a1, kPointerSizeLog2); 181512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a6, a4, Operand(t2)); 181612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a6, a6, Operand(kParameterMapHeaderSize)); 181712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a6, FieldMemOperand(a4, FixedArray::kHeaderSize + 1 * kPointerSize)); 181812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 181912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Copy the parameter slots and the holes in the arguments. 182012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We need to fill in mapped_parameter_count slots. They index the context, 182112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // where parameters are stored in reverse order, at 182212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 182312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The mapped parameter thus need to get indices 182412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // MIN_CONTEXT_SLOTS+parameter_count-1 .. 182512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count 182612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We loop from right to left. 182712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label parameters_loop, parameters_test; 182812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a6, a1); 182912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(t1, MemOperand(sp, 0 * kPointerSize)); 183012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(t1, t1, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); 183112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(t1, t1, Operand(a1)); 183212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a7, Heap::kTheHoleValueRootIndex); 183312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(t2, a6, kPointerSizeLog2); 183412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a3, a4, Operand(t2)); 183512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a3, a3, Operand(kParameterMapHeaderSize)); 183612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 183712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a6 = loop variable (tagged) 183812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 = mapping index (tagged) 183912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3 = address of backing store (tagged) 184012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a4 = address of parameter map (tagged) 184112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a5 = temporary scratch (a.o., for address calculation) 184212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a7 = the hole value 184312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(¶meters_test); 184412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 184512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¶meters_loop); 184612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 184712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(a6, a6, Operand(Smi::FromInt(1))); 184812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(a5, a6, kPointerSizeLog2); 184912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a5, a5, Operand(kParameterMapHeaderSize - kHeapObjectTag)); 185012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(t2, a4, a5); 185112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(t1, MemOperand(t2)); 185212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(a5, a5, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); 185312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(t2, a3, a5); 185412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a7, MemOperand(t2)); 185512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(t1, t1, Operand(Smi::FromInt(1))); 185612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¶meters_test); 185712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(¶meters_loop, ne, a6, Operand(Smi::FromInt(0))); 185812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 185912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&skip_parameter_map); 186012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2 = argument count (tagged) 186112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3 = address of backing store (tagged) 186212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a5 = scratch 186312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Copy arguments header and remaining slots (if there are any). 186412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a5, Heap::kFixedArrayMapRootIndex); 186512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a5, FieldMemOperand(a3, FixedArray::kMapOffset)); 186612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a2, FieldMemOperand(a3, FixedArray::kLengthOffset)); 186712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 186812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label arguments_loop, arguments_test; 186912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(t1, a1); 187012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, MemOperand(sp, 1 * kPointerSize)); 187112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(t2, t1, kPointerSizeLog2); 187212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(a4, a4, Operand(t2)); 187312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&arguments_test); 187412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 187512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&arguments_loop); 187612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(a4, a4, Operand(kPointerSize)); 187712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a6, MemOperand(a4, 0)); 187812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(t2, t1, kPointerSizeLog2); 187912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a5, a3, Operand(t2)); 188012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a6, FieldMemOperand(a5, FixedArray::kHeaderSize)); 188112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(t1, t1, Operand(Smi::FromInt(1))); 188212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 188312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&arguments_test); 188412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&arguments_loop, lt, t1, Operand(a2)); 188512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 188612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Return and remove the on-stack parameters. 188712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(3); 188812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 188912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Do the runtime call to allocate the arguments object. 189012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2 = argument count (tagged) 189112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&runtime); 189212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count. 189312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); 189412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 189512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 189612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1897a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgvoid LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { 1898a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org // Return address is in ra. 1899a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org Label slow; 1900a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 1901a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org Register receiver = LoadDescriptor::ReceiverRegister(); 1902a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org Register key = LoadDescriptor::NameRegister(); 1903a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 1904a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org // Check that the key is an array index, that is Uint32. 1905a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ And(t0, key, Operand(kSmiTagMask | kSmiSignMask)); 1906a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ Branch(&slow, ne, t0, Operand(zero_reg)); 1907a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 1908a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org // Everything is fine, call runtime. 1909a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ Push(receiver, key); // Receiver, key. 1910a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 1911a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org // Perform tail call to the entry. 1912a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ TailCallExternalReference( 1913a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org ExternalReference(IC_Utility(IC::kLoadElementWithInterceptor), 1914a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org masm->isolate()), 1915a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 2, 1); 1916a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 1917a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ bind(&slow); 1918a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org PropertyAccessCompiler::TailCallBuiltin( 1919a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); 1920a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org} 1921a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 1922a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 192312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { 192412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[0] : number of parameters 192512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[4] : receiver displacement 192612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[8] : function 192712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if the calling frame is an arguments adaptor frame. 192812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label adaptor_frame, try_allocate, runtime; 192912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 193012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); 193112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&adaptor_frame, 193212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org eq, 193312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a3, 193412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 193512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 193612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the length from the frame. 193712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a1, MemOperand(sp, 0)); 193812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&try_allocate); 193912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 194012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Patch the arguments.length and the parameters pointer. 194112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&adaptor_frame); 194212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a1, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 194312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a1, MemOperand(sp, 0)); 194412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(at, a1, kPointerSizeLog2); 194512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 194612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a3, a2, Operand(at)); 194712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 194812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset)); 194912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, MemOperand(sp, 1 * kPointerSize)); 195012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 195112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Try the new space allocation. Start out with computing the size 195212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // of the arguments object and the elements array in words. 195312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label add_arguments_object; 195412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&try_allocate); 195512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&add_arguments_object, eq, a1, Operand(zero_reg)); 195612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a1); 195712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 195812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a1, a1, Operand(FixedArray::kHeaderSize / kPointerSize)); 195912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&add_arguments_object); 196012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a1, a1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize)); 196112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 196212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Do the allocation of both objects in one go. 196312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Allocate(a1, v0, a2, a3, &runtime, 196412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); 196512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 196612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the arguments boilerplate from the current native context. 196712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 196812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, FieldMemOperand(a4, GlobalObject::kNativeContextOffset)); 196912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, MemOperand(a4, Context::SlotOffset( 197012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Context::STRICT_ARGUMENTS_MAP_INDEX))); 197112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 197212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a4, FieldMemOperand(v0, JSObject::kMapOffset)); 197312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex); 197412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset)); 197512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); 197612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 197712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the length (smi tagged) and set that as an in-object property too. 197812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 197912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a1, MemOperand(sp, 0 * kPointerSize)); 198012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ AssertSmi(a1); 198112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a1, FieldMemOperand(v0, JSObject::kHeaderSize + 198212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Heap::kArgumentsLengthIndex * kPointerSize)); 198312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 198412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label done; 198512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&done, eq, a1, Operand(zero_reg)); 198612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 198712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the parameters pointer from the stack. 198812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, MemOperand(sp, 1 * kPointerSize)); 198912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 199012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up the elements pointer in the allocated arguments object and 199112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // initialize the header in the elements fixed array. 199212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a4, v0, Operand(Heap::kStrictArgumentsObjectSize)); 199312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset)); 199412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a3, Heap::kFixedArrayMapRootIndex); 199512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, FieldMemOperand(a4, FixedArray::kMapOffset)); 199612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a1, FieldMemOperand(a4, FixedArray::kLengthOffset)); 199712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Untag the length for the loop. 199812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a1); 199912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 200012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 200112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Copy the fixed array slots. 200212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label loop; 200312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up a4 to point to the first array slot. 200412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a4, a4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 200512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&loop); 200612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Pre-decrement a2 with kPointerSize on each iteration. 200712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Pre-decrement in order to skip receiver. 200812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a2, a2, Operand(-kPointerSize)); 200912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, MemOperand(a2)); 201012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Post-increment a4 with kPointerSize on each iteration. 201112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, MemOperand(a4)); 201212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a4, a4, Operand(kPointerSize)); 201312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(a1, a1, Operand(1)); 201412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&loop, ne, a1, Operand(zero_reg)); 201512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 201612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Return and remove the on-stack parameters. 201712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&done); 201812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(3); 201912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 202012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Do the runtime call to allocate the arguments object. 202112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&runtime); 202212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1); 202312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 202412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 202512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 202612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid RegExpExecStub::Generate(MacroAssembler* masm) { 202712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Just jump directly to runtime if native RegExp is not selected at compile 202812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // time or if regexp entry in generated code is turned off runtime switch or 202912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // at compilation. 203012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#ifdef V8_INTERPRETED_REGEXP 203112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1); 203212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#else // V8_INTERPRETED_REGEXP 203312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 203412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stack frame on entry. 203512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[0]: last_match_info (expected JSArray) 203612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[4]: previous index 203712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[8]: subject string 203812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[12]: JSRegExp object 203912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 204012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kLastMatchInfoOffset = 0 * kPointerSize; 204112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kPreviousIndexOffset = 1 * kPointerSize; 204212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kSubjectOffset = 2 * kPointerSize; 204312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kJSRegExpOffset = 3 * kPointerSize; 204412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 204512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label runtime; 204612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Allocation of registers for this function. These are in callee save 204712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // registers and will be preserved by the call to the native RegExp code, as 204812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // this code is called using the normal C calling convention. When calling 204912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // directly from generated code the native RegExp code will not do a GC and 205012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // therefore the content of these registers are safe to use after the call. 205112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // MIPS - using s0..s2, since we are not using CEntry Stub. 205212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register subject = s0; 205312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register regexp_data = s1; 205412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register last_match_info_elements = s2; 205512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 205612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Ensure that a RegExp stack is allocated. 205712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference address_of_regexp_stack_memory_address = 205812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::address_of_regexp_stack_memory_address( 205912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate()); 206012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference address_of_regexp_stack_memory_size = 206112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::address_of_regexp_stack_memory_size(isolate()); 206212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand(address_of_regexp_stack_memory_size)); 206312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, MemOperand(a0, 0)); 206412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, eq, a0, Operand(zero_reg)); 206512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 206612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the first argument is a JSRegExp object. 206712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, MemOperand(sp, kJSRegExpOffset)); 206812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 206912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a0, &runtime); 207012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a0, a1, a1); 207112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, ne, a1, Operand(JS_REGEXP_TYPE)); 207212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 207312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the RegExp has been compiled (data contains a fixed array). 207412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(regexp_data, FieldMemOperand(a0, JSRegExp::kDataOffset)); 207512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_debug_code) { 207612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiTst(regexp_data, a4); 207712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Check(nz, 207812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kUnexpectedTypeForRegExpDataFixedArrayExpected, 207912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a4, 208012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(zero_reg)); 208112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(regexp_data, a0, a0); 208212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Check(eq, 208312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kUnexpectedTypeForRegExpDataFixedArrayExpected, 208412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a0, 208512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(FIXED_ARRAY_TYPE)); 208612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 208712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 208812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // regexp_data: RegExp data (FixedArray) 208912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 209012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); 209112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, ne, a0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); 209212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 209312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // regexp_data: RegExp data (FixedArray) 209412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the number of captures fit in the static offsets vector buffer. 209512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, 209612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 209712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check (number_of_captures + 1) * 2 <= offsets vector size 209812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Or number_of_captures * 2 <= offsets vector size - 2 209912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Or number_of_captures <= offsets vector size / 2 - 1 210012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Multiplying by 2 comes for free since a2 is smi-tagged. 210112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); 210212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int temp = Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1; 210312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, hi, a2, Operand(Smi::FromInt(temp))); 210412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 210512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Reset offset for possibly sliced string. 210612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(t0, zero_reg); 210712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(subject, MemOperand(sp, kSubjectOffset)); 210812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(subject, &runtime); 210912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a3, subject); // Make a copy of the original subject string. 211012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); 211112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 211212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // subject: subject string 211312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3: subject string 211412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a0: subject string instance type 211512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // regexp_data: RegExp data (FixedArray) 211612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Handle subject string according to its encoding and representation: 211712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (1) Sequential string? If yes, go to (5). 211812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (2) Anything but sequential or cons? If yes, go to (6). 211912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (3) Cons string. If the string is flat, replace subject with first string. 212012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Otherwise bailout. 212112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (4) Is subject external? If yes, go to (7). 212212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (5) Sequential string. Load regexp code according to encoding. 212312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (E) Carry on. 212412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org /// [...] 212512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 212612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Deferred code at the end of the stub: 212712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (6) Not a long external string? If yes, go to (8). 212812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (7) External string. Make it, offset-wise, look like a sequential string. 212912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Go to (5). 213012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (8) Short external string or not a string? If yes, bail out to runtime. 213112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (9) Sliced string. Replace subject with parent. Go to (4). 213212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 213312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label check_underlying; // (4) 213412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label seq_string; // (5) 213512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label not_seq_nor_cons; // (6) 213612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label external_string; // (7) 213712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label not_long_external; // (8) 213812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 213912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (1) Sequential string? If yes, go to (5). 214012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a1, 214112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a0, 214212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(kIsNotStringMask | 214312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kStringRepresentationMask | 214412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kShortExternalStringMask)); 214512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); 214612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (5). 214712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 214812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (2) Anything but sequential or cons? If yes, go to (6). 214912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kConsStringTag < kExternalStringTag); 215012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 215112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 215212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 215312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Go to (6). 215412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag)); 215512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 215612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (3) Cons string. Check that it's flat. 215712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Replace subject with first string and reload instance type. 215812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, FieldMemOperand(subject, ConsString::kSecondOffset)); 215912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a1, Heap::kempty_stringRootIndex); 216012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, ne, a0, Operand(a1)); 216112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); 216212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 216312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (4) Is subject external? If yes, go to (7). 216412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&check_underlying); 216512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); 216612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 216712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSeqStringTag == 0); 216812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a0, Operand(kStringRepresentationMask)); 216912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The underlying external string is never a short external string. 217012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); 217112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); 217212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&external_string, ne, at, Operand(zero_reg)); // Go to (7). 217312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 217412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (5) Sequential string. Load regexp code according to encoding. 217512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&seq_string); 217612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // subject: sequential subject string (or look-alike, external string) 217712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3: original subject string 217812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load previous index and check range before a3 is overwritten. We have to 217912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // use a3 instead of subject here because subject might have been only made 218012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // to look like a sequential string when it actually is an external string. 218112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a1, MemOperand(sp, kPreviousIndexOffset)); 218212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(a1, &runtime); 218312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, FieldMemOperand(a3, String::kLengthOffset)); 218412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, ls, a3, Operand(a1)); 218512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a1); 218612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 218712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kStringEncodingMask == 4); 218812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kOneByteStringTag == 4); 218912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kTwoByteStringTag == 0); 21902c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for one_byte. 21912c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org __ ld(t9, FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset)); 21922c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org __ dsra(a3, a0, 2); // a3 is 1 for one_byte, 0 for UC16 (used below). 219312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); 219412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Movz(t9, a5, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. 219512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 219612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (E) Carry on. String handling is done. 219712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // t9: irregexp code 219812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the irregexp code has been generated for the actual string 219912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // encoding. If it has, the field contains a code object otherwise it contains 220012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a smi (code flushing support). 220112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(t9, &runtime); 220212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 220312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: previous index 22042c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // a3: encoding of subject string (1 if one_byte, 0 if two_byte); 220512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // t9: code 220612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // subject: Subject string 220712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // regexp_data: RegExp data (FixedArray) 220812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // All checks done. Now push arguments for native regexp code. 220912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 221012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1, a0, a2); 221112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 221212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Isolates: note we add an additional parameter here (isolate pointer). 221312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kRegExpExecuteArguments = 9; 221412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kParameterRegisters = (kMipsAbi == kN64) ? 8 : 4; 221512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); 221612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 221712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stack pointer now points to cell where return address is to be written. 221812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Arguments are before that on the stack or in registers, meaning we 221912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // treat the return address as argument 5. Thus every argument after that 222012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // needs to be shifted back by 1. Since DirectCEntryStub will handle 222112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // allocating space for the c argument slots, we don't need to calculate 222212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // that into the argument positions on the stack. This is how the stack will 222312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // look (sp meaning the value of sp at this moment): 222412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Abi n64: 222512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // [sp + 1] - Argument 9 222612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // [sp + 0] - saved ra 222712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Abi O32: 222812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // [sp + 5] - Argument 9 222912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // [sp + 4] - Argument 8 223012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // [sp + 3] - Argument 7 223112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // [sp + 2] - Argument 6 223212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // [sp + 1] - Argument 5 223312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // [sp + 0] - saved ra 223412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 223512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (kMipsAbi == kN64) { 223612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 9: Pass current isolate address. 223712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand(ExternalReference::isolate_address(isolate()))); 223812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a0, MemOperand(sp, 1 * kPointerSize)); 223912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 224012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 8: Indicate that this is a direct call from JavaScript. 224112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a7, Operand(1)); 224212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 224312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 7: Start (high end) of backtracking stack memory area. 224412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand(address_of_regexp_stack_memory_address)); 224512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, MemOperand(a0, 0)); 224612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a2, Operand(address_of_regexp_stack_memory_size)); 224712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, MemOperand(a2, 0)); 224812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddu(a6, a0, a2); 224912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 225012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 6: Set the number of capture registers to zero to force global 225112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // regexps to behave as non-global. This does not affect non-global regexps. 225212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a5, zero_reg); 225312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 225412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 5: static offsets vector buffer. 225512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a4, Operand( 225612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::address_of_static_offsets_vector(isolate()))); 225712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { // O32. 2258e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(kMipsAbi == kO32); 225912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 226012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 9: Pass current isolate address. 226112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // CFunctionArgumentOperand handles MIPS stack argument slots. 226212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand(ExternalReference::isolate_address(isolate()))); 226312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a0, MemOperand(sp, 5 * kPointerSize)); 226412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 226512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 8: Indicate that this is a direct call from JavaScript. 226612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand(1)); 226712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a0, MemOperand(sp, 4 * kPointerSize)); 226812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 226912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 7: Start (high end) of backtracking stack memory area. 227012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand(address_of_regexp_stack_memory_address)); 227112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, MemOperand(a0, 0)); 227212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a2, Operand(address_of_regexp_stack_memory_size)); 227312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, MemOperand(a2, 0)); 227412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddu(a0, a0, a2); 227512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a0, MemOperand(sp, 3 * kPointerSize)); 227612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 227712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 6: Set the number of capture registers to zero to force global 227812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // regexps to behave as non-global. This does not affect non-global regexps. 227912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a0, zero_reg); 228012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a0, MemOperand(sp, 2 * kPointerSize)); 228112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 228212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 5: static offsets vector buffer. 228312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand( 228412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::address_of_static_offsets_vector(isolate()))); 228512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a0, MemOperand(sp, 1 * kPointerSize)); 228612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 228712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 228812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // For arguments 4 and 3 get string length, calculate start of string data 22892c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // and calculate the shift of the index (0 for one_byte and 1 for two byte). 229012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(t2, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); 229112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte. 229212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load the length from the original subject string from the previous stack 229312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // frame. Therefore we have to use fp, which points exactly to two pointer 229412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sizes below the previous sp. (Because creating a new stack frame pushes 229512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) 229612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); 229712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If slice offset is not 0, load the length from the original sliced string. 229812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 4, a3: End of string data 229912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 3, a2: Start of string data 230012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Prepare start and end index of the input. 230112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsllv(t1, t0, a3); 230212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddu(t0, t2, t1); 230312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsllv(t1, a1, a3); 230412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddu(a2, t0, t1); 230512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 230612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(t2, FieldMemOperand(subject, String::kLengthOffset)); 230712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 230812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(t2); 230912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsllv(t1, t2, a3); 231012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddu(a3, t0, t1); 231112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 2 (a1): Previous index. 231212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Already there 231312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 231412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Argument 1 (a0): Subject string. 231512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a0, subject); 231612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 231712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Locate the code entry and call it. 231812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); 231912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DirectCEntryStub stub(isolate()); 232012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stub.GenerateCall(masm, t9); 232112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 232212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LeaveExitFrame(false, no_reg, true); 232312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 232412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // v0: result 232512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // subject: subject string (callee saved) 232612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // regexp_data: RegExp data (callee saved) 232712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // last_match_info_elements: Last match info elements (callee saved) 232812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check the result. 232912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label success; 233012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&success, eq, v0, Operand(1)); 233112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We expect exactly one result since we force the called regexp to behave 233212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // as non-global. 233312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label failure; 233412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE)); 233512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If not exception it can only be retry. Handle that in the runtime system. 233612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); 233712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Result must now be exception. If there is no pending exception already a 233812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // stack overflow (on the backtrack stack) was detected in RegExp code but 233912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // haven't created the exception yet. Handle that in the runtime system. 234012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(592): Rerunning the RegExp to get the stack overflow exception. 234112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a1, Operand(isolate()->factory()->the_hole_value())); 234212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 234312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate()))); 234412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(v0, MemOperand(a2, 0)); 234512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, eq, v0, Operand(a1)); 234612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 234712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a1, MemOperand(a2, 0)); // Clear pending exception. 234812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 234912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if the exception is a termination. If so, throw as uncatchable. 235012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a0, Heap::kTerminationExceptionRootIndex); 235112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label termination_exception; 235212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&termination_exception, eq, v0, Operand(a0)); 235312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 235412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Throw(v0); 235512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 235612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&termination_exception); 235712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ThrowUncatchable(v0); 235812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 235912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&failure); 236012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // For failure and exception return null. 236112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(isolate()->factory()->null_value())); 236212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(4); 236312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 236412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Process the result from the native regexp code. 236512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&success); 236612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 236712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lw(a1, UntagSmiFieldMemOperand( 236812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 236912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Calculate number of capture registers (number_of_captures + 1) * 2. 237012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a1, a1, Operand(1)); 237112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsll(a1, a1, 1); // Multiply by 2. 237212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 237312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, MemOperand(sp, kLastMatchInfoOffset)); 237412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a0, &runtime); 237512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a0, a2, a2); 237612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, ne, a2, Operand(JS_ARRAY_TYPE)); 237712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the JSArray is in fast case. 237812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(last_match_info_elements, 237912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(a0, JSArray::kElementsOffset)); 238012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); 238112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kFixedArrayMapRootIndex); 238212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, ne, a0, Operand(at)); 238312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the last match info has space for the capture registers and the 238412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // additional information. 238512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, 238612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); 238712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a2, a1, Operand(RegExpImpl::kLastMatchOverhead)); 238812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 238912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(at, a0); 239012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, gt, a2, Operand(at)); 239112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 239212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: number of capture registers 239312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // subject: subject string 239412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Store the capture count. 239512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiTag(a2, a1); // To smi. 239612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a2, FieldMemOperand(last_match_info_elements, 239712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org RegExpImpl::kLastCaptureCountOffset)); 239812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Store last subject and last input. 239912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(subject, 240012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(last_match_info_elements, 240112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org RegExpImpl::kLastSubjectOffset)); 240212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a2, subject); 240312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ RecordWriteField(last_match_info_elements, 240412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org RegExpImpl::kLastSubjectOffset, 240512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org subject, 240612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a7, 240712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kRAHasNotBeenSaved, 240812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kDontSaveFPRegs); 240912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(subject, a2); 241012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(subject, 241112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(last_match_info_elements, 241212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org RegExpImpl::kLastInputOffset)); 241312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ RecordWriteField(last_match_info_elements, 241412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org RegExpImpl::kLastInputOffset, 241512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org subject, 241612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a7, 241712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kRAHasNotBeenSaved, 241812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kDontSaveFPRegs); 241912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 242012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the static offsets vector filled by the native regexp code. 242112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference address_of_static_offsets_vector = 242212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::address_of_static_offsets_vector(isolate()); 242312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a2, Operand(address_of_static_offsets_vector)); 242412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 242512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: number of capture registers 242612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2: offsets vector 242712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label next_capture, done; 242812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Capture register counter starts from number of capture registers and 242912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // counts down until wrapping after zero. 243012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a0, 243112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org last_match_info_elements, 243212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag)); 243312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&next_capture); 243412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(a1, a1, Operand(1)); 243512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&done, lt, a1, Operand(zero_reg)); 243612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Read the value from the static offsets vector buffer. 243712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lw(a3, MemOperand(a2, 0)); 243812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddiu(a2, a2, kIntSize); 243912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Store the smi value in the last match info. 244012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiTag(a3); 244112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, MemOperand(a0, 0)); 244212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&next_capture, USE_DELAY_SLOT); 244312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddiu(a0, a0, kPointerSize); // In branch delay slot. 244412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 244512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&done); 244612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 244712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Return last match info. 244812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(v0, MemOperand(sp, kLastMatchInfoOffset)); 244912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(4); 245012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 245112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Do the runtime call to execute the regexp. 245212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&runtime); 245312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1); 245412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 245512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Deferred code for string handling. 245612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (6) Not a long external string? If yes, go to (8). 245712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_seq_nor_cons); 245812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Go to (8). 245912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(¬_long_external, gt, a1, Operand(kExternalStringTag)); 246012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 246112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (7) External string. Make it, offset-wise, look like a sequential string. 246212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&external_string); 246312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); 246412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 246512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_debug_code) { 246612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Assert that we do not have a cons or slice (indirect strings) here. 246712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Sequential strings have already been ruled out. 246812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a0, Operand(kIsIndirectStringMask)); 246912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Assert(eq, 247012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kExternalStringExpectedButNotFound, 247112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org at, 247212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(zero_reg)); 247312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 247412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(subject, 247512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(subject, ExternalString::kResourceDataOffset)); 247612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Move the pointer so that offset-wise, it looks like a sequential string. 247712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 247812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(subject, 247912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org subject, 248012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SeqTwoByteString::kHeaderSize - kHeapObjectTag); 248112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&seq_string); // Go to (5). 248212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 248312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (8) Short external string or not a string? If yes, bail out to runtime. 248412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_long_external); 248512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); 248612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask)); 248712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, ne, at, Operand(zero_reg)); 248812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 248912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (9) Sliced string. Replace subject with parent. Go to (4). 249012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load offset into t0 and replace subject string with parent. 249112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset)); 249212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(t0); 249312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); 249412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&check_underlying); // Go to (4). 249512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif // V8_INTERPRETED_REGEXP 249612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 249712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 249812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 249912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void GenerateRecordCallTarget(MacroAssembler* masm) { 250012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Cache the called function in a feedback vector slot. Cache states 250112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // are uninitialized, monomorphic (indicated by a JSFunction), and 250212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // megamorphic. 250312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a0 : number of arguments to the construct function 250412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 : the function to call 250512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2 : Feedback vector 250612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3 : slot in feedback vector (Smi) 250712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label initialize, done, miss, megamorphic, not_array_function; 250812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 2509a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()), 251012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->isolate()->heap()->megamorphic_symbol()); 2511a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()), 251212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->isolate()->heap()->uninitialized_symbol()); 251312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 251412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load the cache state into a4. 251512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsrl(a4, a3, 32 - kPointerSizeLog2); 251612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a4, a2, Operand(a4)); 251712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, FieldMemOperand(a4, FixedArray::kHeaderSize)); 251812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 251912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // A monomorphic cache hit or an already megamorphic state: invoke the 252012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // function without changing the state. 252112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&done, eq, a4, Operand(a1)); 252212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 252312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!FLAG_pretenuring_call_new) { 252412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If we came here, we need to see if we are the array function. 252512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If we didn't have a matching function, and we didn't find the megamorph 252612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sentinel, then we have in the slot either some other function or an 252712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // AllocationSite. Do a map check on the object in a3. 252812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(a4, 0)); 252912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); 253012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, ne, a5, Operand(at)); 253112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 253212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Make sure the function is the Array() function 253312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, a4); 253412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&megamorphic, ne, a1, Operand(a4)); 253512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&done); 253612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 253712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 253812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 253912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 254012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // A monomorphic miss (i.e, here the cache is not uninitialized) goes 254112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // megamorphic. 254212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kUninitializedSymbolRootIndex); 254312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&initialize, eq, a4, Operand(at)); 254412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // MegamorphicSentinel is an immortal immovable object (undefined) so no 254512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // write-barrier is needed. 254612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&megamorphic); 254712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsrl(a4, a3, 32- kPointerSizeLog2); 254812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a4, a2, Operand(a4)); 254912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex); 255012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize)); 255112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&done); 255212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 255312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // An uninitialized cache is patched with the function. 255412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&initialize); 255512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!FLAG_pretenuring_call_new) { 255612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Make sure the function is the Array() function. 255712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, a4); 255812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(¬_array_function, ne, a1, Operand(a4)); 255912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 256012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The target function is the Array constructor, 256112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Create an AllocationSite if we don't already have it, store it in the 256212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // slot. 256312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 256412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 256512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const RegList kSavedRegs = 256612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1 << 4 | // a0 256712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1 << 5 | // a1 256812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1 << 6 | // a2 256912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1 << 7; // a3 257012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 257112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Arguments register must be smi-tagged to call out. 257212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiTag(a0); 257312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPush(kSavedRegs); 257412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 257512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CreateAllocationSiteStub create_stub(masm->isolate()); 257612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallStub(&create_stub); 257712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 257812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPop(kSavedRegs); 257912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a0); 258012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 258112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&done); 258212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 258312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_array_function); 258412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 258512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 258612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsrl(a4, a3, 32 - kPointerSizeLog2); 258712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a4, a2, Operand(a4)); 258812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a4, a4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 258912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a1, MemOperand(a4, 0)); 259012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 259112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(a4, a2, a1); 259212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ RecordWrite(a2, a4, a1, kRAHasNotBeenSaved, kDontSaveFPRegs, 259312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 259412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Pop(a4, a2, a1); 259512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 259612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&done); 259712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 259812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 259912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 260012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { 260112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 260212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 260312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Do not transform the receiver for strict mode functions. 260412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t strict_mode_function_mask = 260512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1 << SharedFunctionInfo::kStrictModeBitWithinByte ; 260612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Do not transform the receiver for native (Compilerhints already in a3). 260712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t native_mask = 1 << SharedFunctionInfo::kNativeBitWithinByte; 260812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 260912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(a4, FieldMemOperand(a3, SharedFunctionInfo::kStrictModeByteOffset)); 261012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a4, Operand(strict_mode_function_mask)); 261112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(cont, ne, at, Operand(zero_reg)); 261212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(a4, FieldMemOperand(a3, SharedFunctionInfo::kNativeByteOffset)); 261312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a4, Operand(native_mask)); 261412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(cont, ne, at, Operand(zero_reg)); 261512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 261612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 261712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 261812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitSlowCase(MacroAssembler* masm, 261912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int argc, 262012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* non_function) { 262112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check for function proxy. 262212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(non_function, ne, a4, Operand(JS_FUNCTION_PROXY_TYPE)); 262312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ push(a1); // put proxy as additional argument 262412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand(argc + 1, RelocInfo::NONE32)); 262512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a2, zero_reg); 262612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY); 262712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 262812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Handle<Code> adaptor = 262912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); 263012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Jump(adaptor, RelocInfo::CODE_TARGET); 263112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 263212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 263312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 263412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // of the original receiver from the call site). 263512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(non_function); 263612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a1, MemOperand(sp, argc * kPointerSize)); 263712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand(argc)); // Set up the number of arguments. 263812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a2, zero_reg); 263912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION); 264012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 264112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org RelocInfo::CODE_TARGET); 264212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 264312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 264412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 264512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { 264612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Wrap the receiver and patch it back onto the stack. 264712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { FrameScope frame_scope(masm, StackFrame::INTERNAL); 264812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(a1, a3); 264912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 265012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ pop(a1); 265112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 265212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(USE_DELAY_SLOT, cont); 265312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(v0, MemOperand(sp, argc * kPointerSize)); 265412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 265512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 265612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 265712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void CallFunctionNoFeedback(MacroAssembler* masm, 265812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int argc, bool needs_checks, 265912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool call_as_method) { 266012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 : the function to call 266112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label slow, non_function, wrap, cont; 266212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 266312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (needs_checks) { 266412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the function is really a JavaScript function. 266512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: pushed function (to be verified) 266612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a1, &non_function); 266712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 266812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Goto slow case if we do not have a function. 266912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a1, a4, a4); 267012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&slow, ne, a4, Operand(JS_FUNCTION_TYPE)); 267112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 267212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 267312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Fast-case: Invoke the function now. 267412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: pushed function 267512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ParameterCount actual(argc); 267612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 267712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (call_as_method) { 267812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (needs_checks) { 267912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitContinueIfStrictOrNative(masm, &cont); 268012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 268112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 268212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute the receiver in sloppy mode. 268312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, MemOperand(sp, argc * kPointerSize)); 268412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 268512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (needs_checks) { 268612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a3, &wrap); 268712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a3, a4, a4); 268812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&wrap, lt, a4, Operand(FIRST_SPEC_OBJECT_TYPE)); 268912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 269012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&wrap); 269112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 269212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 269312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&cont); 269412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 269512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ InvokeFunction(a1, actual, JUMP_FUNCTION, NullCallWrapper()); 269612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 269712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (needs_checks) { 269812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Slow-case: Non-function called. 269912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&slow); 270012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitSlowCase(masm, argc, &non_function); 270112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 270212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 270312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (call_as_method) { 270412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&wrap); 270512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Wrap the receiver and patch it back onto the stack. 270612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitWrapCase(masm, argc, &cont); 270712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 270812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 270912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 271012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 271112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid CallFunctionStub::Generate(MacroAssembler* masm) { 2712fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); 271312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 271412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 271512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 271612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid CallConstructStub::Generate(MacroAssembler* masm) { 271712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a0 : number of arguments 271812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 : the function to call 271912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2 : feedback vector 272012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3 : (only if a2 is not undefined) slot in feedback vector (Smi) 272112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label slow, non_function_call; 272212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the function is not a smi. 272312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a1, &non_function_call); 272412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the function is a JSFunction. 272512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a1, a4, a4); 272612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&slow, ne, a4, Operand(JS_FUNCTION_TYPE)); 272712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 272812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (RecordCallTarget()) { 272912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateRecordCallTarget(masm); 273012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 273112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsrl(at, a3, 32 - kPointerSizeLog2); 273212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a5, a2, at); 273312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_pretenuring_call_new) { 273412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Put the AllocationSite from the feedback vector into a2. 273512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // By adding kPointerSize we encode that we know the AllocationSite 273612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // entry is at the feedback vector slot given by a3 + 1. 273712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, FieldMemOperand(a5, FixedArray::kHeaderSize + kPointerSize)); 273812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 273912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label feedback_register_initialized; 274012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Put the AllocationSite from the feedback vector into a2, or undefined. 274112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, FieldMemOperand(a5, FixedArray::kHeaderSize)); 274212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(a2, AllocationSite::kMapOffset)); 274312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); 274412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&feedback_register_initialized, eq, a5, Operand(at)); 274512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); 274612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&feedback_register_initialized); 274712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 274812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 274912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ AssertUndefinedOrAllocationSite(a2, a5); 275012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 275112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 275212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Jump to the function-specific construct stub. 275312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register jmp_reg = a4; 275412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(jmp_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 275512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(jmp_reg, FieldMemOperand(jmp_reg, 275612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SharedFunctionInfo::kConstructStubOffset)); 275712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(at, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); 275812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Jump(at); 275912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 276012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a0: number of arguments 276112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: called object 276212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a4: object type 276312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label do_call; 276412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&slow); 276512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&non_function_call, ne, a4, Operand(JS_FUNCTION_PROXY_TYPE)); 276612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); 276712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&do_call); 276812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 276912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&non_function_call); 277012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 277112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&do_call); 277212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set expected number of arguments to zero (not changing r0). 277312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a2, Operand(0, RelocInfo::NONE32)); 277412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 277512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org RelocInfo::CODE_TARGET); 277612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 277712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 277812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 277912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// StringCharCodeAtGenerator. 278012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 2781e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!a4.is(index_)); 2782e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!a4.is(result_)); 2783e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!a4.is(object_)); 278412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 278512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If the receiver is a smi trigger the non-string case. 278612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(object_, receiver_not_string_); 278712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 278812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Fetch the instance type of the receiver into result register. 278912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 279012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 279112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If the receiver is not a string trigger the non-string case. 279212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a4, result_, Operand(kIsNotStringMask)); 279312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(receiver_not_string_, ne, a4, Operand(zero_reg)); 279412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 279512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If the index is non-smi trigger the non-smi case. 279612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(index_, &index_not_smi_); 279712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 279812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&got_smi_index_); 279912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 280012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check for index out of range. 280112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, FieldMemOperand(object_, String::kLengthOffset)); 280212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(index_out_of_range_, ls, a4, Operand(index_)); 280312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 280412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(index_); 280512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 280612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org StringCharLoadGenerator::Generate(masm, 280712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org object_, 280812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org index_, 280912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org result_, 281012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &call_runtime_); 281112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 281212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiTag(result_); 281312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&exit_); 281412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 281512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 281612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 281712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { 281812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 281912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(vector, FieldMemOperand(vector, 282012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org JSFunction::kSharedFunctionInfoOffset)); 282112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(vector, FieldMemOperand(vector, 282212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SharedFunctionInfo::kFeedbackVectorOffset)); 282312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 282412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 282512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 282612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid CallIC_ArrayStub::Generate(MacroAssembler* masm) { 282712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 - function 282812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3 - slot id 282912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 283012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 283112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitLoadTypeFeedbackVector(masm, a2); 283212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 283312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, at); 283412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, ne, a1, Operand(at)); 283512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 283612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a0, Operand(arg_count())); 283712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsrl(at, a3, 32 - kPointerSizeLog2); 283812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(at, a2, Operand(at)); 2839dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ ld(a4, FieldMemOperand(at, FixedArray::kHeaderSize)); 2840dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org 2841dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // Verify that a4 contains an AllocationSite 2842dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ ld(a5, FieldMemOperand(a4, HeapObject::kMapOffset)); 2843dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); 2844dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ Branch(&miss, ne, a5, Operand(at)); 2845dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org 2846dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ mov(a2, a4); 284712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ArrayConstructorStub stub(masm->isolate(), arg_count()); 284812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallStub(&stub); 284912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 285012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 2851d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org GenerateMiss(masm); 285212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 285312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The slow case, we need this no matter what to complete a call after a miss. 285412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CallFunctionNoFeedback(masm, 2855fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org arg_count(), 2856fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org true, 2857fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org CallAsMethod()); 285812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 285912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Unreachable. 286012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ stop("Unexpected code address"); 286112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 286212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 286312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 286412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid CallICStub::Generate(MacroAssembler* masm) { 286512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 - function 286612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3 - slot id (Smi) 286712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label extra_checks_or_miss, slow_start; 286812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label slow, non_function, wrap, cont; 286912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label have_js_function; 2870fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org int argc = arg_count(); 287112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ParameterCount actual(argc); 287212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 287312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitLoadTypeFeedbackVector(masm, a2); 287412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 287512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The checks. First, does r1 match the recorded monomorphic target? 287612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsrl(a4, a3, 32 - kPointerSizeLog2); 287712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a4, a2, Operand(a4)); 287812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, FieldMemOperand(a4, FixedArray::kHeaderSize)); 287912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&extra_checks_or_miss, ne, a1, Operand(a4)); 288012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 288112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&have_js_function); 2882fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org if (CallAsMethod()) { 288312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitContinueIfStrictOrNative(masm, &cont); 288412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute the receiver in sloppy mode. 288512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, MemOperand(sp, argc * kPointerSize)); 288612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 288712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a3, &wrap); 288812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a3, a4, a4); 288912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&wrap, lt, a4, Operand(FIRST_SPEC_OBJECT_TYPE)); 289012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 289112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&cont); 289212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 289312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 289412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ InvokeFunction(a1, actual, JUMP_FUNCTION, NullCallWrapper()); 289512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 289612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&slow); 289712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitSlowCase(masm, argc, &non_function); 289812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 2899fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org if (CallAsMethod()) { 290012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&wrap); 290112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EmitWrapCase(masm, argc, &cont); 290212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 290312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 290412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&extra_checks_or_miss); 290512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 290612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 290712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex); 290812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&slow_start, eq, a4, Operand(at)); 290912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kUninitializedSymbolRootIndex); 291012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, eq, a4, Operand(at)); 291112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 291212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!FLAG_trace_ic) { 2913dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // We are going megamorphic. If the feedback is a JSFunction, it is fine 2914dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // to handle it here. More complex cases are dealt with in the runtime. 2915dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ AssertNotSmi(a4); 2916dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ GetObjectType(a4, a5, a5); 2917dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org __ Branch(&miss, ne, a5, Operand(JS_FUNCTION_TYPE)); 291812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsrl(a4, a3, 32 - kPointerSizeLog2); 291912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a4, a2, Operand(a4)); 292012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex); 292112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize)); 292212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&slow_start); 292312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 292412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 292512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We are here because tracing is on or we are going monomorphic. 292612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 2927d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org GenerateMiss(masm); 292812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 292912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the slow case 293012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&slow_start); 293112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the function is really a JavaScript function. 293212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // r1: pushed function (to be verified) 293312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a1, &non_function); 293412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 293512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Goto slow case if we do not have a function. 293612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a1, a4, a4); 293712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&slow, ne, a4, Operand(JS_FUNCTION_TYPE)); 293812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&have_js_function); 293912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 294012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 294112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 2942d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.orgvoid CallICStub::GenerateMiss(MacroAssembler* masm) { 294312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the receiver of the function from the stack; 1 ~ return address. 2944fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org __ ld(a4, MemOperand(sp, (arg_count() + 1) * kPointerSize)); 294512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 294612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 294712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 294812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 294912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Push the receiver and the function and feedback info. 295012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(a4, a1, a2, a3); 295112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 295212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Call the entry. 2953d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss 2954d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org : IC::kCallIC_Customization_Miss; 2955d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org 295612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference miss = ExternalReference(IC_Utility(id), 295712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->isolate()); 295812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallExternalReference(miss, 4); 295912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 296012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Move result to a1 and exit the internal frame. 296112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a1, v0); 296212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 296312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 296412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 296512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 296612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid StringCharCodeAtGenerator::GenerateSlow( 296712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MacroAssembler* masm, 296812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const RuntimeCallHelper& call_helper) { 296912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase); 297012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 297112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Index is not a smi. 297212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&index_not_smi_); 297312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If index is a heap number, try converting it to an integer. 297412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CheckMap(index_, 297512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org result_, 297612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Heap::kHeapNumberMapRootIndex, 297712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org index_not_number_, 297812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DONT_DO_SMI_CHECK); 297912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org call_helper.BeforeCall(masm); 298012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Consumed by runtime conversion function: 298112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(object_, index_); 298212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (index_flags_ == STRING_INDEX_IS_NUMBER) { 298312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); 298412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 2985e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 298612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // NumberToSmi discards numbers that are not exact integers. 298712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallRuntime(Runtime::kNumberToSmi, 1); 298812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 298912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 299012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Save the conversion result before the pop instructions below 299112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // have a chance to overwrite it. 299212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 299312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(index_, v0); 299412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ pop(object_); 299512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Reload the instance type. 299612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 299712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 299812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org call_helper.AfterCall(masm); 299912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If index is still not a smi, it must be out of range. 300012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(index_, index_out_of_range_); 300112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Otherwise, return to the fast path. 300212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&got_smi_index_); 300312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 300412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Call runtime. We get here when the receiver is a string and the 300512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // index is a number, but the code of getting the actual character 300612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // is too complex (e.g., when the string needs to be flattened). 300712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&call_runtime_); 300812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org call_helper.BeforeCall(masm); 300912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiTag(index_); 301012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(object_, index_); 301112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallRuntime(Runtime::kStringCharCodeAtRT, 2); 301212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 301312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(result_, v0); 301412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 301512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org call_helper.AfterCall(masm); 301612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&exit_); 301712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 301812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); 301912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 302012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 302112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 302212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// ------------------------------------------------------------------------- 302312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// StringCharFromCodeGenerator 302412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 302512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 302612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Fast case of Heap::LookupSingleCharacterStringFromCode. 302712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 3028e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!a4.is(result_)); 3029e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!a4.is(code_)); 303012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 303112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 303221d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCode + 1)); 303312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a4, 303412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org code_, 303512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(kSmiTagMask | 303612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ((~String::kMaxOneByteCharCode) << kSmiTagSize))); 303712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&slow_case_, ne, a4, Operand(zero_reg)); 303812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 303912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 304012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); 30412c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // At this point code register contains smi tagged one_byte char code. 304212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 304312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(a4, code_, kPointerSizeLog2); 304412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(result_, result_, a4); 304512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); 304612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a4, Heap::kUndefinedValueRootIndex); 304712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&slow_case_, eq, result_, Operand(a4)); 304812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&exit_); 304912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 305012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 305112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 305212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid StringCharFromCodeGenerator::GenerateSlow( 305312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MacroAssembler* masm, 305412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const RuntimeCallHelper& call_helper) { 305512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); 305612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 305712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&slow_case_); 305812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org call_helper.BeforeCall(masm); 305912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ push(code_); 306012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallRuntime(Runtime::kCharFromCode, 1); 306112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(result_, v0); 306212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 306312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org call_helper.AfterCall(masm); 306412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&exit_); 306512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 306612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 306712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 306812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 306912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 30702c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgenum CopyCharactersFlags { COPY_ONE_BYTE = 1, DEST_ALWAYS_ALIGNED = 2 }; 307112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 307212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 307312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid StringHelper::GenerateCopyCharacters(MacroAssembler* masm, 307412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register dest, 307512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register src, 307612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register count, 307712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register scratch, 307812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org String::Encoding encoding) { 307912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_debug_code) { 308012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that destination is word aligned. 308112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(scratch, dest, Operand(kPointerAlignmentMask)); 308212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Check(eq, 308312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kDestinationOfCopyNotAligned, 308412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org scratch, 308512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(zero_reg)); 308612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 308712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 308812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Assumes word reads and writes are little endian. 308912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Nothing to do for zero characters. 309012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label done; 309112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 309212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (encoding == String::TWO_BYTE_ENCODING) { 309312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(count, count, count); 309412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 309512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 309612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register limit = count; // Read until dest equals this. 309712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(limit, dest, Operand(count)); 309812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 309912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label loop_entry, loop; 310012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Copy bytes from src to dest until dest hits limit. 310112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&loop_entry); 310212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&loop); 310312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(scratch, MemOperand(src)); 310412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddiu(src, src, 1); 310512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sb(scratch, MemOperand(dest)); 310612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddiu(dest, dest, 1); 310712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&loop_entry); 310812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&loop, lt, dest, Operand(limit)); 310912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 311012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&done); 311112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 311212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 311312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 311412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid SubStringStub::Generate(MacroAssembler* masm) { 311512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label runtime; 311612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stack frame on entry. 311712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ra: return address 311812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[0]: to 311912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[4]: from 312012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[8]: string 312112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 312212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This stub is called from the native-call %_SubString(...), so 312312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // nothing can be assumed about the arguments. It is tested that: 312412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // "string" is a sequential string, 312512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // both "from" and "to" are smis, and 312612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // 0 <= from <= to <= string.length. 312712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If any of these assumptions fail, we call the runtime system. 312812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 312912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kToOffset = 0 * kPointerSize; 313012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kFromOffset = 1 * kPointerSize; 313112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kStringOffset = 2 * kPointerSize; 313212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 313312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, MemOperand(sp, kToOffset)); 313412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, MemOperand(sp, kFromOffset)); 313512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Does not needed? 313612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// STATIC_ASSERT(kFromOffset == kToOffset + 4); 313712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 313812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Does not needed? 313912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 314012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 314112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Utilize delay slots. SmiUntag doesn't emit a jump, everything else is 314212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // safe in this case. 314312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(a2, &runtime); 314412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(a3, &runtime); 314512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Both a2 and a3 are untagged integers. 314612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 314712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a2, a2); 314812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a3, a3); 314912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, lt, a3, Operand(zero_reg)); // From < 0. 315012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 315112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, gt, a3, Operand(a2)); // Fail if from > to. 315212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(a2, a2, a3); 315312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 315412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Make sure first argument is a string. 315512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(v0, MemOperand(sp, kStringOffset)); 315612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(v0, &runtime); 315712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); 315812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset)); 315912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a4, a1, Operand(kIsNotStringMask)); 316012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 316112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, ne, a4, Operand(zero_reg)); 316212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 316312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label single_char; 316412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&single_char, eq, a2, Operand(1)); 316512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 316612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Short-cut for the case of trivial substring. 316712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label return_v0; 316812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // v0: original string 316912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2: result string length 317012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, FieldMemOperand(v0, String::kLengthOffset)); 317112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a4); 317212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Return original string. 317312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&return_v0, eq, a2, Operand(a4)); 317412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Longer than original string's length or negative: unsafe arguments. 317512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, hi, a2, Operand(a4)); 317612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Shorter than original string's length: an actual substring. 317712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 317812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Deal with different string types: update the index if necessary 317912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // and put the underlying string into a5. 318012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // v0: original string 318112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: instance type 318212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2: length 318312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3: from index (untagged) 318412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label underlying_unpacked, sliced_string, seq_or_external_string; 318512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If the string is not indirect, it can only be sequential or external. 318612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); 318712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kIsIndirectStringMask != 0); 318812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a4, a1, Operand(kIsIndirectStringMask)); 318912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(USE_DELAY_SLOT, &seq_or_external_string, eq, a4, Operand(zero_reg)); 319012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a4 is used as a scratch register and can be overwritten in either case. 319112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a4, a1, Operand(kSlicedNotConsMask)); 319212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&sliced_string, ne, a4, Operand(zero_reg)); 319312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Cons string. Check whether it is flat, then fetch first part. 319412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(v0, ConsString::kSecondOffset)); 319512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(a4, Heap::kempty_stringRootIndex); 319612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, ne, a5, Operand(a4)); 319712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(v0, ConsString::kFirstOffset)); 319812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Update instance type. 319912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a1, FieldMemOperand(a5, HeapObject::kMapOffset)); 320012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset)); 320112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&underlying_unpacked); 320212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 320312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&sliced_string); 320412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Sliced string. Fetch parent and correct start index by offset. 320512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(v0, SlicedString::kParentOffset)); 320612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, FieldMemOperand(v0, SlicedString::kOffsetOffset)); 320712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a4); // Add offset to index. 320812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a3, a3, a4); 320912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Update instance type. 321012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a1, FieldMemOperand(a5, HeapObject::kMapOffset)); 321112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset)); 321212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&underlying_unpacked); 321312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 321412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&seq_or_external_string); 321512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Sequential or external string. Just move string to the expected register. 321612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a5, v0); 321712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 321812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&underlying_unpacked); 321912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 322012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_string_slices) { 322112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label copy_routine; 322212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a5: underlying subject string 322312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: instance type of underlying subject string 322412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2: length 322512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3: adjusted start index (untagged) 322612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Short slice. Copy instead of slicing. 322712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(©_routine, lt, a2, Operand(SlicedString::kMinLength)); 322812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Allocate new sliced string. At this point we do not reload the instance 322912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // type including the string encoding because we simply rely on the info 323012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // provided by the original string. It does not matter if the original 323112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // string's encoding is wrong because we always have to recheck encoding of 323212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the newly created string's parent anyways due to externalized strings. 323312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label two_byte_slice, set_slice_header; 323412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); 323512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 323612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a4, a1, Operand(kStringEncodingMask)); 323712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&two_byte_slice, eq, a4, Operand(zero_reg)); 32382c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org __ AllocateOneByteSlicedString(v0, a2, a6, a7, &runtime); 323912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&set_slice_header); 324012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&two_byte_slice); 324112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ AllocateTwoByteSlicedString(v0, a2, a6, a7, &runtime); 324212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&set_slice_header); 324312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiTag(a3); 324412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a5, FieldMemOperand(v0, SlicedString::kParentOffset)); 324512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a3, FieldMemOperand(v0, SlicedString::kOffsetOffset)); 324612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&return_v0); 324712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 324812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(©_routine); 324912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 325012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 325112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a5: underlying subject string 325212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: instance type of underlying subject string 325312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2: length 325412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3: adjusted start index (untagged) 325512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label two_byte_sequential, sequential_string, allocate_result; 325612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kExternalStringTag != 0); 325712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSeqStringTag == 0); 325812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a4, a1, Operand(kExternalStringTag)); 325912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&sequential_string, eq, a4, Operand(zero_reg)); 326012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 326112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Handle external string. 326212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Rule out short external strings. 326312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kShortExternalStringTag != 0); 326412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a4, a1, Operand(kShortExternalStringTag)); 326512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&runtime, ne, a4, Operand(zero_reg)); 326612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(a5, ExternalString::kResourceDataOffset)); 326712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a5 already points to the first character of underlying string. 326812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&allocate_result); 326912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 327012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&sequential_string); 327112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Locate first character of underlying subject string. 327212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 327312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a5, a5, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 327412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 327512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&allocate_result); 327612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Sequential acii string. Allocate the result. 327712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); 327812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a4, a1, Operand(kStringEncodingMask)); 327912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&two_byte_sequential, eq, a4, Operand(zero_reg)); 328012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 32812c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Allocate and copy the resulting one_byte string. 32822c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org __ AllocateOneByteString(v0, a2, a4, a6, a7, &runtime); 328312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 328412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Locate first character of substring to copy. 328512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a5, a5, a3); 328612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 328712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Locate first character of result. 328812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a1, v0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 328912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 329012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // v0: result string 329112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: first character of result string 329212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2: result string length 329312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a5: first character of substring to copy 329412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); 329512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org StringHelper::GenerateCopyCharacters( 329612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm, a1, a5, a2, a3, String::ONE_BYTE_ENCODING); 329712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&return_v0); 329812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 329912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Allocate and copy the resulting two-byte string. 330012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&two_byte_sequential); 330112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ AllocateTwoByteString(v0, a2, a4, a6, a7, &runtime); 330212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 330312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Locate first character of substring to copy. 330412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 330512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsll(a4, a3, 1); 330612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a5, a5, a4); 330712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Locate first character of result. 330812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 330912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 331012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // v0: result string. 331112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: first character of result. 331212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2: result length. 331312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a5: first character of substring to copy. 331412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 331512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org StringHelper::GenerateCopyCharacters( 331612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm, a1, a5, a2, a3, String::TWO_BYTE_ENCODING); 331712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 331812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&return_v0); 331912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Counters* counters = isolate()->counters(); 332012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ IncrementCounter(counters->sub_string_native(), 1, a3, a4); 332112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(3); 332212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 332312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Just jump to runtime to create the sub string. 332412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&runtime); 332512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kSubString, 3, 1); 332612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 332712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&single_char); 332812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // v0: original string 332912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: instance type 333012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2: length 333112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3: from index (untagged) 333212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org StringCharAtGenerator generator( 333312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org v0, a3, a2, v0, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); 333412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org generator.GenerateFast(masm); 333512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(3); 333612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org generator.SkipSlow(masm, &runtime); 333712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 333812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 333912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 33402c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid StringHelper::GenerateFlatOneByteStringEquals( 33412c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org MacroAssembler* masm, Register left, Register right, Register scratch1, 33422c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org Register scratch2, Register scratch3) { 334312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register length = scratch1; 334412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 334512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compare lengths. 334612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label strings_not_equal, check_zero_length; 334712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(length, FieldMemOperand(left, String::kLengthOffset)); 334812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(scratch2, FieldMemOperand(right, String::kLengthOffset)); 334912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&check_zero_length, eq, length, Operand(scratch2)); 335012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&strings_not_equal); 335112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Can not put li in delayslot, it has multi instructions. 335212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(NOT_EQUAL))); 335312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 335412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 335512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if the length is zero. 335612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label compare_chars; 335712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&check_zero_length); 335812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 335912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&compare_chars, ne, length, Operand(zero_reg)); 3360e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(is_int16((intptr_t)Smi::FromInt(EQUAL))); 336112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 336212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(EQUAL))); 336312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 336412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compare characters. 336512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&compare_chars); 336612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 33672c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, scratch3, 33682c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org v0, &strings_not_equal); 336912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 337012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Characters are equal. 337112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 337212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(EQUAL))); 337312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 337412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 337512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 33762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid StringHelper::GenerateCompareFlatOneByteStrings( 33779aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org MacroAssembler* masm, Register left, Register right, Register scratch1, 33789aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org Register scratch2, Register scratch3, Register scratch4) { 337912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label result_not_equal, compare_lengths; 338012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Find minimum length and length difference. 338112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(scratch1, FieldMemOperand(left, String::kLengthOffset)); 338212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(scratch2, FieldMemOperand(right, String::kLengthOffset)); 338312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(scratch3, scratch1, Operand(scratch2)); 338412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register length_delta = scratch3; 338512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ slt(scratch4, scratch2, scratch1); 338612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Movn(scratch1, scratch2, scratch4); 338712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register min_length = scratch1; 338812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 338912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&compare_lengths, eq, min_length, Operand(zero_reg)); 339012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 339112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compare loop. 33922c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2, 33932c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org scratch4, v0, &result_not_equal); 339412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 339512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compare lengths - strings up to min-length are equal. 339612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&compare_lengths); 3397e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); 339812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Use length_delta as result if it's zero. 339912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(scratch2, length_delta); 340012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(scratch4, zero_reg); 340112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, zero_reg); 340212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 340312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&result_not_equal); 340412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Conditionally update the result based either on length_delta or 340512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the last comparion performed in the loop above. 340612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label ret; 340712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&ret, eq, scratch2, Operand(scratch4)); 340812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(GREATER))); 340912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&ret, gt, scratch2, Operand(scratch4)); 341012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(LESS))); 341112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&ret); 341212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 341312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 341412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 341512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 34162c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid StringHelper::GenerateOneByteCharsCompareLoop( 34179aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org MacroAssembler* masm, Register left, Register right, Register length, 34189aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org Register scratch1, Register scratch2, Register scratch3, 341912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* chars_not_equal) { 342012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Change index to run from -length to -1 by adding length to string 342112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // start. This means that loop ends when index reaches zero, which 342212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // doesn't need an additional compare. 342312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(length); 342412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(scratch1, length, 342512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 342612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(left, left, Operand(scratch1)); 342712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(right, right, Operand(scratch1)); 342812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(length, zero_reg, length); 342912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register index = length; // index = -length; 343012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 343112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 343212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compare loop. 343312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label loop; 343412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&loop); 343512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(scratch3, left, index); 343612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(scratch1, MemOperand(scratch3)); 343712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(scratch3, right, index); 343812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(scratch2, MemOperand(scratch3)); 343912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(chars_not_equal, ne, scratch1, Operand(scratch2)); 344012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(index, index, 1); 344112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&loop, ne, index, Operand(zero_reg)); 344212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 344312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 344412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 344512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid StringCompareStub::Generate(MacroAssembler* masm) { 344612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label runtime; 344712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 344812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Counters* counters = isolate()->counters(); 344912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 345012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stack frame on entry. 345112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[0]: right string 345212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[4]: left string 345312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a1, MemOperand(sp, 1 * kPointerSize)); // Left. 345412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, MemOperand(sp, 0 * kPointerSize)); // Right. 345512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 345612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label not_same; 345712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(¬_same, ne, a0, Operand(a1)); 345812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(EQUAL == 0); 345912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 346012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(EQUAL))); 346112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ IncrementCounter(counters->string_compare_native(), 1, a1, a2); 346212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DropAndRet(2); 346312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 346412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_same); 346512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 34662c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Check that both objects are sequential one_byte strings. 34672c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org __ JumpIfNotBothSequentialOneByteStrings(a1, a0, a2, a3, &runtime); 346812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 34692c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Compare flat one_byte strings natively. Remove arguments from stack first. 347012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ IncrementCounter(counters->string_compare_native(), 1, a2, a3); 347112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(sp, sp, Operand(2 * kPointerSize)); 34722c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org StringHelper::GenerateCompareFlatOneByteStrings(masm, a1, a0, a2, a3, a4, a5); 347312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 347412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&runtime); 347512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 347612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 347712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 347812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 347912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { 348012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------- S t a t e ------------- 348112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a1 : left 348212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a0 : right 348312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- ra : return address 348412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------------------------------- 348512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 348612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load a2 with the allocation site. We stick an undefined dummy value here 348712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // and replace it with the real allocation site later when we instantiate this 348812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate(). 348912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a2, handle(isolate()->heap()->undefined_value())); 349012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 349112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Make sure that we actually patched the allocation site. 349212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_debug_code) { 349312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a2, Operand(kSmiTagMask)); 349412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Assert(ne, kExpectedAllocationSite, at, Operand(zero_reg)); 349512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, FieldMemOperand(a2, HeapObject::kMapOffset)); 349612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); 349712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Assert(eq, kExpectedAllocationSite, a4, Operand(at)); 349812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 349912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 350012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Tail call into the stub that handles binary operations with allocation 350112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sites. 35025fc1eed70f85bd1e9d0833742945798d6ef49cf0machenbach@chromium.org BinaryOpWithAllocationSiteStub stub(isolate(), state()); 350312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallStub(&stub); 350412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 350512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 350612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 35079aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.orgvoid CompareICStub::GenerateSmis(MacroAssembler* masm) { 3508d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org DCHECK(state() == CompareICState::SMI); 350912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 351012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Or(a2, a1, a0); 351112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(a2, &miss); 351212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 351312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (GetCondition() == eq) { 351412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // For equality we do not care about the sign of the result. 351512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 351612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(v0, a0, a1); 351712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 351812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Untag before subtracting to avoid handling overflow. 351912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a1); 352012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a0); 352112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 352212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(v0, a1, a0); 352312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 352412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 352512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 352612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateMiss(masm); 352712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 352812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 352912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 35309aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.orgvoid CompareICStub::GenerateNumbers(MacroAssembler* masm) { 3531d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org DCHECK(state() == CompareICState::NUMBER); 353212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 353312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label generic_stub; 353412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label unordered, maybe_undefined1, maybe_undefined2; 353512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 353612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 3537d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org if (left() == CompareICState::SMI) { 353812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(a1, &miss); 353912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 3540d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org if (right() == CompareICState::SMI) { 354112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotSmi(a0, &miss); 354212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 354312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 354412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Inlining the double comparison and falling back to the general compare 354512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // stub if NaN is involved. 354612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load left and right operand. 354712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label done, left, left_smi, right_smi; 354812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a0, &right_smi); 354912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CheckMap(a0, a2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, 355012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DONT_DO_SMI_CHECK); 355112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(a2, a0, Operand(kHeapObjectTag)); 355212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ldc1(f2, MemOperand(a2, HeapNumber::kValueOffset)); 355312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&left); 355412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&right_smi); 355512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a2, a0); // Can't clobber a0 yet. 355612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FPURegister single_scratch = f6; 355712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mtc1(a2, single_scratch); 355812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ cvt_d_w(f2, single_scratch); 355912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 356012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&left); 356112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a1, &left_smi); 356212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CheckMap(a1, a2, Heap::kHeapNumberMapRootIndex, &maybe_undefined2, 356312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DONT_DO_SMI_CHECK); 356412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(a2, a1, Operand(kHeapObjectTag)); 356512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ldc1(f0, MemOperand(a2, HeapNumber::kValueOffset)); 356612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&done); 356712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&left_smi); 356812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a2, a1); // Can't clobber a1 yet. 356912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org single_scratch = f8; 357012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mtc1(a2, single_scratch); 357112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ cvt_d_w(f0, single_scratch); 357212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 357312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&done); 357412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 357512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Return a result of -1, 0, or 1, or use CompareStub for NaNs. 357612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label fpu_eq, fpu_lt; 357712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Test if equal, and also handle the unordered/NaN case. 357812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ BranchF(&fpu_eq, &unordered, eq, f0, f2); 357912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 358012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Test if less (unordered case is already handled). 358112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ BranchF(&fpu_lt, NULL, lt, f0, f2); 358212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 358312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Otherwise it's greater, so just fall thru, and return. 3584e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(is_int16(GREATER) && is_int16(EQUAL) && is_int16(LESS)); 358512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 358612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(GREATER)); 358712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 358812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&fpu_eq); 358912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 359012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(EQUAL)); 359112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 359212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&fpu_lt); 359312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 359412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(LESS)); 359512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 359612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&unordered); 359712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&generic_stub); 3598d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org CompareICStub stub(isolate(), op(), CompareICState::GENERIC, 3599d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org CompareICState::GENERIC, CompareICState::GENERIC); 360012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 360112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 360212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&maybe_undefined1); 360321d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org if (Token::IsOrderedRelationalCompareOp(op())) { 360412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 360512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, ne, a0, Operand(at)); 360612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a1, &unordered); 360712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a1, a2, a2); 360812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE)); 360912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ jmp(&unordered); 361012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 361112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 361212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&maybe_undefined2); 361321d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org if (Token::IsOrderedRelationalCompareOp(op())) { 361412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 361512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&unordered, eq, a1, Operand(at)); 361612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 361712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 361812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 361912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateMiss(masm); 362012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 362112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 362212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 36239aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.orgvoid CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { 3624d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org DCHECK(state() == CompareICState::INTERNALIZED_STRING); 362512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 362612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 362712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Registers containing left and right operands respectively. 362812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register left = a1; 362912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register right = a0; 363012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register tmp1 = a2; 363112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register tmp2 = a3; 363212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 363312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that both operands are heap objects. 363412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfEitherSmi(left, right, &miss); 363512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 363612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that both operands are internalized strings. 363712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 363812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 363912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 364012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 364112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 364212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Or(tmp1, tmp1, Operand(tmp2)); 364312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 364412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, ne, at, Operand(zero_reg)); 364512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 364612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Make sure a0 is non-zero. At this point input operands are 364712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // guaranteed to be non-zero. 3648e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(right.is(a0)); 364912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(EQUAL == 0); 365012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 365112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, right); 365212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Internalized strings are compared by identity. 365312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(ne, left, Operand(right)); 3654e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(is_int16(EQUAL)); 365512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 365612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(EQUAL))); 365712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 365812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 365912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateMiss(masm); 366012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 366112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 366212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 36639aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.orgvoid CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { 3664d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org DCHECK(state() == CompareICState::UNIQUE_NAME); 3665e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(GetCondition() == eq); 366612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 366712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 366812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Registers containing left and right operands respectively. 366912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register left = a1; 367012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register right = a0; 367112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register tmp1 = a2; 367212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register tmp2 = a3; 367312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 367412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that both operands are heap objects. 367512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfEitherSmi(left, right, &miss); 367612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 367712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that both operands are unique names. This leaves the instance 367812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // types loaded in tmp1 and tmp2. 367912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 368012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 368112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 368212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 368312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 368406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ JumpIfNotUniqueNameInstanceType(tmp1, &miss); 368506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ JumpIfNotUniqueNameInstanceType(tmp2, &miss); 368612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 368712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Use a0 as result 368812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, a0); 368912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 369012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Unique names are compared by identity. 369112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label done; 369212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&done, ne, left, Operand(right)); 369312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Make sure a0 is non-zero. At this point input operands are 369412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // guaranteed to be non-zero. 3695e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(right.is(a0)); 369612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(EQUAL == 0); 369712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 369812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(v0, Operand(Smi::FromInt(EQUAL))); 369912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&done); 370012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 370112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 370212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 370312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateMiss(masm); 370412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 370512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 370612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 37079aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.orgvoid CompareICStub::GenerateStrings(MacroAssembler* masm) { 3708d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org DCHECK(state() == CompareICState::STRING); 370912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 371012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 371121d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org bool equality = Token::IsEqualityOp(op()); 371212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 371312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Registers containing left and right operands respectively. 371412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register left = a1; 371512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register right = a0; 371612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register tmp1 = a2; 371712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register tmp2 = a3; 371812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register tmp3 = a4; 371912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register tmp4 = a5; 372012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register tmp5 = a6; 372112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 372212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that both operands are heap objects. 372312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfEitherSmi(left, right, &miss); 372412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 372512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that both operands are strings. This leaves the instance 372612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // types loaded in tmp1 and tmp2. 372712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 372812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 372912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 373012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 373112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kNotStringTag != 0); 373212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Or(tmp3, tmp1, tmp2); 373312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(tmp5, tmp3, Operand(kIsNotStringMask)); 373412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, ne, tmp5, Operand(zero_reg)); 373512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 373612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Fast check for identical strings. 373712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label left_ne_right; 373812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(EQUAL == 0); 373912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 374012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&left_ne_right, ne, left, Operand(right)); 374112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 374212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, zero_reg); // In the delay slot. 374312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&left_ne_right); 374412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 374512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Handle not identical strings. 374612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 374712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that both strings are internalized strings. If they are, we're done 374812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // because we already know they are not identical. We know they are both 374912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // strings. 375012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (equality) { 3751e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(GetCondition() == eq); 375212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(kInternalizedTag == 0); 375312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Or(tmp3, tmp1, Operand(tmp2)); 375412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(tmp5, tmp3, Operand(kIsNotInternalizedMask)); 375512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label is_symbol; 375612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&is_symbol, ne, tmp5, Operand(zero_reg)); 375712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Make sure a0 is non-zero. At this point input operands are 375812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // guaranteed to be non-zero. 3759e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(right.is(a0)); 376012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 376112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, a0); // In the delay slot. 376212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&is_symbol); 376312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 376412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 37652c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Check that both strings are sequential one_byte. 376612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label runtime; 37672c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4, 37682c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org &runtime); 376912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 37702c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Compare flat one_byte strings. Returns when done. 377112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (equality) { 37722c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, tmp2, 37732c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org tmp3); 377412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 37752c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1, 37762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org tmp2, tmp3, tmp4); 377712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 377812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 377912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Handle more complex cases in runtime. 378012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&runtime); 378112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(left, right); 378212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (equality) { 378312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kStringEquals, 2, 1); 378412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 378512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 378612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 378712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 378812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 378912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateMiss(masm); 379012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 379112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 379212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 37939aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.orgvoid CompareICStub::GenerateObjects(MacroAssembler* masm) { 3794d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org DCHECK(state() == CompareICState::OBJECT); 379512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 379612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a2, a1, Operand(a0)); 379712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a2, &miss); 379812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 379912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a0, a2, a2); 380012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); 380112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a1, a2, a2); 380212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); 380312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 3804e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(GetCondition() == eq); 380512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 380612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsubu(v0, a0, a1); 380712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 380812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 380912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateMiss(masm); 381012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 381112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 381212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 38139aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.orgvoid CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { 381412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label miss; 381512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a2, a1, a0); 381612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a2, &miss); 381712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, FieldMemOperand(a0, HeapObject::kMapOffset)); 381812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, FieldMemOperand(a1, HeapObject::kMapOffset)); 381912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, ne, a2, Operand(known_map_)); 382012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&miss, ne, a3, Operand(known_map_)); 382112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 382212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 382312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsubu(v0, a0, a1); 382412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 382512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&miss); 382612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateMiss(masm); 382712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 382812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 382912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 38309aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.orgvoid CompareICStub::GenerateMiss(MacroAssembler* masm) { 383112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 383212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Call the runtime system in a fresh internal frame. 383312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference miss = 383412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); 383512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 383612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(a1, a0); 383712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(ra, a1, a0); 383821d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org __ li(a4, Operand(Smi::FromInt(op()))); 383912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddiu(sp, sp, -kPointerSize); 384012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallExternalReference(miss, 3, USE_DELAY_SLOT); 384112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a4, MemOperand(sp)); // In the delay slot. 384212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute the entry point of the rewritten stub. 384312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a2, v0, Operand(Code::kHeaderSize - kHeapObjectTag)); 384412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Restore registers. 384512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Pop(a1, a0, ra); 384612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 384712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Jump(a2); 384812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 384912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 385012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 385112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid DirectCEntryStub::Generate(MacroAssembler* masm) { 385212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Make place for arguments to fit C calling convention. Most of the callers 385312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // of DirectCEntryStub::GenerateCall are using EnterExitFrame/LeaveExitFrame 385412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // so they handle stack restoring and we don't have to do that here. 385512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Any caller of DirectCEntryStub::GenerateCall must take care of dropping 385612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // kCArgsSlotsSize stack space after the call. 385712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ daddiu(sp, sp, -kCArgsSlotsSize); 385812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Place the return address on the stack, making the call 385912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // GC safe. The RegExp backend also relies on this. 386012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(ra, MemOperand(sp, kCArgsSlotsSize)); 386112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Call(t9); // Call the C++ function. 386212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(t9, MemOperand(sp, kCArgsSlotsSize)); 386312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 386412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_debug_code && FLAG_enable_slow_asserts) { 386512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // In case of an error the return address may point to a memory area 386612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // filled with kZapValue by the GC. 386712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Dereference the address and check for this. 386812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Uld(a4, MemOperand(t9)); 386912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Assert(ne, kReceivedInvalidReturnAddress, a4, 387012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(reinterpret_cast<uint64_t>(kZapValue))); 387112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 387212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Jump(t9); 387312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 387412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 387512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 387612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid DirectCEntryStub::GenerateCall(MacroAssembler* masm, 387712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register target) { 387812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org intptr_t loc = 387912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(GetCode().location()); 388012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(t9, target); 388112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(ra, Operand(loc, RelocInfo::CODE_TARGET), CONSTANT_SIZE); 388212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Call(ra); 388312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 388412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 388512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 388612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, 388712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* miss, 388812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* done, 388912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register receiver, 389012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register properties, 389112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Handle<Name> name, 389212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register scratch0) { 3893e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(name->IsUniqueName()); 389412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If names of slots in range from 1 to kProbes - 1 for the hash value are 389512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // not equal to the name and kProbes-th slot is not used (its name is the 389612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // undefined value), it guarantees the hash table doesn't contain the 389712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // property. It's true even if some slots represent deleted properties 389812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // (their names are the hole value). 389912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 0; i < kInlinedProbes; i++) { 390012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // scratch0 points to properties hash. 390112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute the masked index: (hash + i + i * i) & mask. 390212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register index = scratch0; 390312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Capacity is smi 2^n. 390412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiLoadUntag(index, FieldMemOperand(properties, kCapacityOffset)); 390512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(index, index, Operand(1)); 390612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(index, index, 390712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(name->Hash() + NameDictionary::GetProbeOffset(i))); 390812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 390912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Scale the index by multiplying by the entry size. 3910e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(NameDictionary::kEntrySize == 3); 391112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsll(at, index, 1); 391212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(index, index, at); // index *= 3. 391312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 391412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register entity_name = scratch0; 391512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Having undefined at this place means the name is not contained. 3916e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(kSmiTagSize, 1); 391712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register tmp = properties; 391812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 391912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsll(scratch0, index, kPointerSizeLog2); 392012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(tmp, properties, scratch0); 392112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); 392212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 3923e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!tmp.is(entity_name)); 392412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); 392512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(done, eq, entity_name, Operand(tmp)); 392612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 392712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load the hole ready for use below: 392812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); 392912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 393012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stop if found the property. 393112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(miss, eq, entity_name, Operand(Handle<Name>(name))); 393212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 393312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label good; 393412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&good, eq, entity_name, Operand(tmp)); 393512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 393612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if the entry name is not a unique name. 393712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); 393812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(entity_name, 393912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); 394006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ JumpIfNotUniqueNameInstanceType(entity_name, miss); 394112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&good); 394212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 394312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Restore the properties. 394412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(properties, 394512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 394612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 394712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 394812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int spill_mask = 394912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (ra.bit() | a6.bit() | a5.bit() | a4.bit() | a3.bit() | 395012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a2.bit() | a1.bit() | a0.bit() | v0.bit()); 395112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 395212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPush(spill_mask); 395312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 395412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a1, Operand(Handle<Name>(name))); 395512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org NameDictionaryLookupStub stub(masm->isolate(), NEGATIVE_LOOKUP); 395612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallStub(&stub); 395712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(at, v0); 395812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPop(spill_mask); 395912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 396012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(done, eq, at, Operand(zero_reg)); 396112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(miss, ne, at, Operand(zero_reg)); 396212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 396312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 396412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 396512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Probe the name dictionary in the |elements| register. Jump to the 396612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// |done| label if a property with the given name is found. Jump to 396712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// the |miss| label otherwise. 396812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// If lookup was successful |scratch2| will be equal to elements + 4 * index. 396912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, 397012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* miss, 397112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label* done, 397212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register elements, 397312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register name, 397412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register scratch1, 397512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register scratch2) { 3976e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!elements.is(scratch1)); 3977e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!elements.is(scratch2)); 3978e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!name.is(scratch1)); 3979e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!name.is(scratch2)); 398012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 398112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ AssertName(name); 398212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 398312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute the capacity mask. 398412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(scratch1, FieldMemOperand(elements, kCapacityOffset)); 398512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(scratch1); 398612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(scratch1, scratch1, Operand(1)); 398712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 398812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Generate an unrolled loop that performs a few probes before 398912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // giving up. Measurements done on Gmail indicate that 2 probes 399012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // cover ~93% of loads from dictionaries. 399112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 0; i < kInlinedProbes; i++) { 399212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute the masked index: (hash + i + i * i) & mask. 399312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lwu(scratch2, FieldMemOperand(name, Name::kHashFieldOffset)); 399412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (i > 0) { 399512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Add the probe offset (i + i * i) left shifted to avoid right shifting 399612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the hash in a separate instruction. The value hash + i + i * i is right 399712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // shifted in the following and instruction. 3998e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(NameDictionary::GetProbeOffset(i) < 399912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1 << (32 - Name::kHashFieldOffset)); 400012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(scratch2, scratch2, Operand( 400112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org NameDictionary::GetProbeOffset(i) << Name::kHashShift)); 400212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 400312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsrl(scratch2, scratch2, Name::kHashShift); 400412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(scratch2, scratch1, scratch2); 400512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 400612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Scale the index by multiplying by the element size. 4007e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(NameDictionary::kEntrySize == 3); 400812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // scratch2 = scratch2 * 3. 400912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 401012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsll(at, scratch2, 1); 401112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(scratch2, scratch2, at); 401212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 401312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if the key is identical to the name. 401412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsll(at, scratch2, kPointerSizeLog2); 401512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(scratch2, elements, at); 401612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(at, FieldMemOperand(scratch2, kElementsStartOffset)); 401712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(done, eq, name, Operand(at)); 401812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 401912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 402012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int spill_mask = 402112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (ra.bit() | a6.bit() | a5.bit() | a4.bit() | 402212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a3.bit() | a2.bit() | a1.bit() | a0.bit() | v0.bit()) & 402312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ~(scratch1.bit() | scratch2.bit()); 402412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 402512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPush(spill_mask); 402612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (name.is(a0)) { 4027e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!elements.is(a1)); 402812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(a1, name); 402912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(a0, elements); 403012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 403112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(a0, elements); 403212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(a1, name); 403312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 403412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org NameDictionaryLookupStub stub(masm->isolate(), POSITIVE_LOOKUP); 403512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallStub(&stub); 403612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(scratch2, a2); 403712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(at, v0); 403812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPop(spill_mask); 403912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 404012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(done, ne, at, Operand(zero_reg)); 404112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(miss, eq, at, Operand(zero_reg)); 404212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 404312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 404412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 404512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid NameDictionaryLookupStub::Generate(MacroAssembler* masm) { 404612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This stub overrides SometimesSetsUpAFrame() to return false. That means 404712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // we cannot call anything that could cause a GC from this stub. 404812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Registers: 404912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // result: NameDictionary to probe 405012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1: key 405112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // dictionary: NameDictionary to probe. 405212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // index: will hold an index of entry if lookup is successful. 405312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // might alias with result_. 405412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Returns: 405512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // result_ is zero if lookup failed, non zero otherwise. 405612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 405712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register result = v0; 405812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register dictionary = a0; 405912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register key = a1; 406012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register index = a2; 406112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register mask = a3; 406212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register hash = a4; 406312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register undefined = a5; 406412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register entry_key = a6; 406512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 406612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label in_dictionary, maybe_in_dictionary, not_in_dictionary; 406712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 406812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(mask, FieldMemOperand(dictionary, kCapacityOffset)); 406912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(mask); 407012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(mask, mask, Operand(1)); 407112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 407212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lwu(hash, FieldMemOperand(key, Name::kHashFieldOffset)); 407312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 407412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); 407512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 407612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = kInlinedProbes; i < kTotalProbes; i++) { 407712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute the masked index: (hash + i + i * i) & mask. 407812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Capacity is smi 2^n. 407912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (i > 0) { 408012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Add the probe offset (i + i * i) left shifted to avoid right shifting 408112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the hash in a separate instruction. The value hash + i + i * i is right 408212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // shifted in the following and instruction. 4083e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(NameDictionary::GetProbeOffset(i) < 408412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1 << (32 - Name::kHashFieldOffset)); 408512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(index, hash, Operand( 408612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org NameDictionary::GetProbeOffset(i) << Name::kHashShift)); 408712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 408812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(index, hash); 408912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 409012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsrl(index, index, Name::kHashShift); 409112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(index, mask, index); 409212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 409312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Scale the index by multiplying by the entry size. 4094e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(NameDictionary::kEntrySize == 3); 409512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // index *= 3. 409612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(at, index); 409712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsll(index, index, 1); 409812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(index, index, at); 409912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 410012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 4101e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(kSmiTagSize, 1); 410212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsll(index, index, kPointerSizeLog2); 410312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(index, index, dictionary); 410412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(entry_key, FieldMemOperand(index, kElementsStartOffset)); 410512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 410612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Having undefined at this place means the name is not contained. 410712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(¬_in_dictionary, eq, entry_key, Operand(undefined)); 410812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 410912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stop if found the property. 411012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&in_dictionary, eq, entry_key, Operand(key)); 411112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 41129aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) { 411312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if the entry name is not a unique name. 411412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); 411512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(entry_key, 411612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); 411706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ JumpIfNotUniqueNameInstanceType(entry_key, &maybe_in_dictionary); 411812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 411912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 412012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 412112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&maybe_in_dictionary); 412212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If we are doing negative lookup then probing failure should be 412312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // treated as a lookup success. For positive lookup probing failure 412412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // should be treated as lookup failure. 41259aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org if (mode() == POSITIVE_LOOKUP) { 412612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 412712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(result, zero_reg); 412812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 412912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 413012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&in_dictionary); 413112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 413212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(result, 1); 413312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 413412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_in_dictionary); 413512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 413612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(result, zero_reg); 413712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 413812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 413912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 414012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 414112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Isolate* isolate) { 414212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs); 414312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stub1.GetCode(); 414412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Hydrogen code stubs need stub2 at snapshot time. 414512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org StoreBufferOverflowStub stub2(isolate, kSaveFPRegs); 414612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stub2.GetCode(); 414712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 414812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 414912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 415012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Takes the input in 3 registers: address_ value_ and object_. A pointer to 415112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// the value has just been written into the object, now this stub makes sure 415212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// we keep the GC informed. The word in the object where the value has been 415312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// written is in the address register. 415412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid RecordWriteStub::Generate(MacroAssembler* masm) { 415512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label skip_to_incremental_noncompacting; 415612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label skip_to_incremental_compacting; 415712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 415812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The first two branch+nop instructions are generated with labels so as to 415912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // get the offset fixed up correctly by the bind(Label*) call. We patch it 416012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // back and forth between a "bne zero_reg, zero_reg, ..." (a nop in this 416112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // position) and the "beq zero_reg, zero_reg, ..." when we start and stop 416212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // incremental heap marking. 416312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // See RecordWriteStub::Patch for details. 416412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ beq(zero_reg, zero_reg, &skip_to_incremental_noncompacting); 416512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ nop(); 416612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ beq(zero_reg, zero_reg, &skip_to_incremental_compacting); 416712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ nop(); 416812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 41699aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org if (remembered_set_action() == EMIT_REMEMBERED_SET) { 41709aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ RememberedSetHelper(object(), 41719aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org address(), 41729aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org value(), 41739aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org save_fp_regs_mode(), 417412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MacroAssembler::kReturnAtEnd); 417512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 417612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 417712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 417812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&skip_to_incremental_noncompacting); 417912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateIncremental(masm, INCREMENTAL); 418012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 418112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&skip_to_incremental_compacting); 418212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateIncremental(masm, INCREMENTAL_COMPACTION); 418312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 418412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. 418512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Will be checked in IncrementalMarking::ActivateGeneratedStub. 418612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 418712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PatchBranchIntoNop(masm, 0); 418812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PatchBranchIntoNop(masm, 2 * Assembler::kInstrSize); 418912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 419012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 419112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 419212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { 419312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.Save(masm); 419412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 41959aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org if (remembered_set_action() == EMIT_REMEMBERED_SET) { 419612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label dont_need_remembered_set; 419712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 419812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(regs_.scratch0(), MemOperand(regs_.address(), 0)); 419912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. 420012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.scratch0(), 420112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &dont_need_remembered_set); 420212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 420312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CheckPageFlag(regs_.object(), 420412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.scratch0(), 420512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1 << MemoryChunk::SCAN_ON_SCAVENGE, 420612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ne, 420712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &dont_need_remembered_set); 420812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 420912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // First notify the incremental marker if necessary, then update the 421012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // remembered set. 421112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CheckNeedsToInformIncrementalMarker( 421212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); 421312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InformIncrementalMarker(masm); 421412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.Restore(masm); 42159aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ RememberedSetHelper(object(), 42169aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org address(), 42179aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org value(), 42189aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org save_fp_regs_mode(), 421912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MacroAssembler::kReturnAtEnd); 422012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 422112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&dont_need_remembered_set); 422212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 422312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 422412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CheckNeedsToInformIncrementalMarker( 422512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm, kReturnOnNoNeedToInformIncrementalMarker, mode); 422612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InformIncrementalMarker(masm); 422712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.Restore(masm); 422812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 422912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 423012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 423112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 423212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { 42339aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode()); 423412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int argument_count = 3; 423512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ PrepareCallCFunction(argument_count, regs_.scratch0()); 423612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register address = 423712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a0.is(regs_.address()) ? regs_.scratch0() : regs_.address(); 4238e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!address.is(regs_.object())); 4239e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!address.is(a0)); 424012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(address, regs_.address()); 424112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(a0, regs_.object()); 424212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Move(a1, address); 424312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a2, Operand(ExternalReference::isolate_address(isolate()))); 424412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 424512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org AllowExternalCallThatCantCauseGC scope(masm); 424612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallCFunction( 424712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::incremental_marking_record_write_function(isolate()), 424812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org argument_count); 42499aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode()); 425012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 425112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 425212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 425312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid RecordWriteStub::CheckNeedsToInformIncrementalMarker( 425412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MacroAssembler* masm, 425512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org OnNoNeedToInformIncrementalMarker on_no_need, 425612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Mode mode) { 425712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label on_black; 425812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label need_incremental; 425912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label need_incremental_pop_scratch; 426012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 426112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(regs_.scratch0(), regs_.object(), Operand(~Page::kPageAlignmentMask)); 426212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(regs_.scratch1(), 426312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MemOperand(regs_.scratch0(), 426412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MemoryChunk::kWriteBarrierCounterOffset)); 426512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(regs_.scratch1(), regs_.scratch1(), Operand(1)); 426612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(regs_.scratch1(), 426712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MemOperand(regs_.scratch0(), 426812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MemoryChunk::kWriteBarrierCounterOffset)); 426912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&need_incremental, lt, regs_.scratch1(), Operand(zero_reg)); 427012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 427112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Let's look at the color of the object: If it is not black we don't have 427212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // to inform the incremental marker. 427312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black); 427412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 427512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.Restore(masm); 427612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 42779aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ RememberedSetHelper(object(), 42789aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org address(), 42799aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org value(), 42809aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org save_fp_regs_mode(), 428112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MacroAssembler::kReturnAtEnd); 428212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 428312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 428412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 428512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 428612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&on_black); 428712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 428812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the value from the slot. 428912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(regs_.scratch0(), MemOperand(regs_.address(), 0)); 429012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 429112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (mode == INCREMENTAL_COMPACTION) { 429212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label ensure_not_white; 429312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 429412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CheckPageFlag(regs_.scratch0(), // Contains value. 429512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.scratch1(), // Scratch. 429612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MemoryChunk::kEvacuationCandidateMask, 429712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org eq, 429812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &ensure_not_white); 429912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 430012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CheckPageFlag(regs_.object(), 430112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.scratch1(), // Scratch. 430212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MemoryChunk::kSkipEvacuationSlotsRecordingMask, 430312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org eq, 430412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &need_incremental); 430512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 430612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&ensure_not_white); 430712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 430812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 430912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We need extra registers for this, so we push the object and the address 431012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // register temporarily. 431112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(regs_.object(), regs_.address()); 431212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ EnsureNotWhite(regs_.scratch0(), // The value. 431312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.scratch1(), // Scratch. 431412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.object(), // Scratch. 431512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.address(), // Scratch. 431612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &need_incremental_pop_scratch); 431712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Pop(regs_.object(), regs_.address()); 431812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 431912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org regs_.Restore(masm); 432012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 43219aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org __ RememberedSetHelper(object(), 43229aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org address(), 43239aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org value(), 43249aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org save_fp_regs_mode(), 432512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MacroAssembler::kReturnAtEnd); 432612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 432712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 432812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 432912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 433012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&need_incremental_pop_scratch); 433112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Pop(regs_.object(), regs_.address()); 433212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 433312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&need_incremental); 433412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 433512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Fall through when we need to inform the incremental marker. 433612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 433712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 433812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 433912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { 434012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------- S t a t e ------------- 434112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a0 : element value to store 434212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a3 : element index as smi 434312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- sp[0] : array literal index in function as smi 434412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- sp[4] : array literal 434512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // clobbers a1, a2, a4 434612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------------------------------- 434712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 434812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label element_done; 434912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label double_elements; 435012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label smi_element; 435112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label slow_elements; 435212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label fast_elements; 435312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 435412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get array literal index, array literal and its map. 435512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, MemOperand(sp, 0 * kPointerSize)); 435612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a1, MemOperand(sp, 1 * kPointerSize)); 435712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a2, FieldMemOperand(a1, JSObject::kMapOffset)); 435812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 435912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CheckFastElements(a2, a5, &double_elements); 436012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check for FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS elements 436112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ JumpIfSmi(a0, &smi_element); 436212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CheckFastSmiElements(a2, a5, &fast_elements); 436312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 436412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Store into the array literal requires a elements transition. Call into 436512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the runtime. 436612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&slow_elements); 436712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // call. 436812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(a1, a3, a0); 436912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 437012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(a5, JSFunction::kLiteralsOffset)); 437112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(a5, a4); 437212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1); 437312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 437412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object. 437512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&fast_elements); 437612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(a1, JSObject::kElementsOffset)); 437712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(a6, a3, kPointerSizeLog2); 437812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a6, a5, a6); 437912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a6, a6, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 438012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a0, MemOperand(a6, 0)); 438112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Update the write barrier for the array store. 438212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ RecordWrite(a5, a6, a0, kRAHasNotBeenSaved, kDontSaveFPRegs, 438312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 438412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 438512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, a0); 438612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 438712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS, 438812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // and value is Smi. 438912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&smi_element); 439012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(a1, JSObject::kElementsOffset)); 439112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiScale(a6, a3, kPointerSizeLog2); 439212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a6, a5, a6); 439312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a0, FieldMemOperand(a6, FixedArray::kHeaderSize)); 439412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 439512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, a0); 439612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 439712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Array literal has ElementsKind of FAST_*_DOUBLE_ELEMENTS. 439812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&double_elements); 439912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(a1, JSObject::kElementsOffset)); 440012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ StoreNumberToDoubleElements(a0, a3, a5, a7, t1, a2, &slow_elements); 440112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 440212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(v0, a0); 440312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 440412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 440512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 440612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid StubFailureTrampolineStub::Generate(MacroAssembler* masm) { 440712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CEntryStub ces(isolate(), 1, kSaveFPRegs); 440812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); 440912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int parameter_count_offset = 441012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; 441112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a1, MemOperand(fp, parameter_count_offset)); 4412fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org if (function_mode() == JS_FUNCTION_STUB_MODE) { 441312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a1, a1, Operand(1)); 441412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 441512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); 441612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ dsll(a1, a1, kPointerSizeLog2); 441712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(USE_DELAY_SLOT); 441812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(sp, sp, a1); 441912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 442012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 442112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 44227b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.orgvoid LoadICTrampolineStub::Generate(MacroAssembler* masm) { 44239aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); 44247b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org VectorLoadStub stub(isolate(), state()); 44257b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 44267b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org} 44277b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org 44287b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org 44297b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.orgvoid KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { 44309aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); 44317b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org VectorKeyedLoadStub stub(isolate()); 44327b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 44337b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org} 44347b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org 44357b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org 443612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { 443712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (masm->isolate()->function_entry_hook() != NULL) { 443812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ProfileEntryHookStub stub(masm->isolate()); 443912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ push(ra); 444012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallStub(&stub); 444112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ pop(ra); 444212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 444312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 444412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 444512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 444612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid ProfileEntryHookStub::Generate(MacroAssembler* masm) { 444712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The entry hook is a "push ra" instruction, followed by a call. 444812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Note: on MIPS "push" is 2 instruction 444912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int32_t kReturnAddressDistanceFromFunctionStart = 445012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Assembler::kCallTargetAddressOffset + (2 * Assembler::kInstrSize); 445112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 445212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This should contain all kJSCallerSaved registers. 445312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const RegList kSavedRegs = 445412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kJSCallerSaved | // Caller saved registers. 445512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org s5.bit(); // Saved stack pointer. 445612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 445712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We also save ra, so the count here is one higher than the mask indicates. 445812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int32_t kNumSavedRegs = kNumJSCallerSaved + 2; 445912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 446012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Save all caller-save registers as this may be called from anywhere. 446112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPush(kSavedRegs | ra.bit()); 446212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 446312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute the function's address for the first argument. 446412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(a0, ra, Operand(kReturnAddressDistanceFromFunctionStart)); 446512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 446612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The caller's return address is above the saved temporaries. 446712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Grab that for the second argument to the hook. 446812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a1, sp, Operand(kNumSavedRegs * kPointerSize)); 446912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 447012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Align the stack if necessary. 447112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int frame_alignment = masm->ActivationFrameAlignment(); 447212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (frame_alignment > kPointerSize) { 447312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(s5, sp); 447421d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org DCHECK(base::bits::IsPowerOfTwo32(frame_alignment)); 447512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(sp, sp, Operand(-frame_alignment)); 447612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 447712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 447812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Dsubu(sp, sp, kCArgsSlotsSize); 447912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#if defined(V8_HOST_ARCH_MIPS) || defined(V8_HOST_ARCH_MIPS64) 448012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t entry_hook = 448112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<int64_t>(isolate()->function_entry_hook()); 448212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(t9, Operand(entry_hook)); 448312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#else 448412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Under the simulator we need to indirect the entry hook through a 448512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // trampoline function at a known address. 448612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // It additionally takes an isolate as a third parameter. 448712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(a2, Operand(ExternalReference::isolate_address(isolate()))); 448812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 448912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); 449012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(t9, Operand(ExternalReference(&dispatcher, 449112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::BUILTIN_CALL, 449212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate()))); 449312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif 449412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Call C function through t9 to conform ABI for PIC. 449512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Call(t9); 449612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 449712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Restore the stack pointer if needed. 449812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (frame_alignment > kPointerSize) { 449912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(sp, s5); 450012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 450112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(sp, sp, kCArgsSlotsSize); 450212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 450312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 450412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Also pop ra to get Ret(0). 450512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ MultiPop(kSavedRegs | ra.bit()); 450612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Ret(); 450712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 450812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 450912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 451012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtemplate<class T> 451112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void CreateArrayDispatch(MacroAssembler* masm, 451212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org AllocationSiteOverrideMode mode) { 451312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (mode == DISABLE_ALLOCATION_SITES) { 451412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org T stub(masm->isolate(), GetInitialFastElementsKind(), mode); 451512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallStub(&stub); 451612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (mode == DONT_OVERRIDE) { 451712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int last_index = GetSequenceIndexFromFastElementsKind( 451812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TERMINAL_FAST_ELEMENTS_KIND); 451912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 0; i <= last_index; ++i) { 452012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 452112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org T stub(masm->isolate(), kind); 452212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallStub(&stub, eq, a3, Operand(kind)); 452312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 452412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 452512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If we reached this point there is a problem. 452612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Abort(kUnexpectedElementsKindInArrayConstructor); 452712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 452812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 452912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 453012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 453112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 453212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 453312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void CreateArrayDispatchOneArgument(MacroAssembler* masm, 453412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org AllocationSiteOverrideMode mode) { 453512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2 - allocation site (if mode != DISABLE_ALLOCATION_SITES) 453612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3 - kind (if mode != DISABLE_ALLOCATION_SITES) 453712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a0 - number of arguments 453812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 - constructor? 453912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp[0] - last argument 454012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label normal_sequence; 454112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (mode == DONT_OVERRIDE) { 4542e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_SMI_ELEMENTS == 0); 4543e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_HOLEY_SMI_ELEMENTS == 1); 4544e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_ELEMENTS == 2); 4545e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_HOLEY_ELEMENTS == 3); 4546e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_DOUBLE_ELEMENTS == 4); 4547e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_HOLEY_DOUBLE_ELEMENTS == 5); 454812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 454912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // is the low bit set? If so, we are holey and that is good. 455012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a3, Operand(1)); 455112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&normal_sequence, ne, at, Operand(zero_reg)); 455212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 455312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // look at the first argument 455412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, MemOperand(sp, 0)); 455512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&normal_sequence, eq, a5, Operand(zero_reg)); 455612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 455712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (mode == DISABLE_ALLOCATION_SITES) { 455812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ElementsKind initial = GetInitialFastElementsKind(); 455912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ElementsKind holey_initial = GetHoleyElementsKind(initial); 456012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 456112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ArraySingleArgumentConstructorStub stub_holey(masm->isolate(), 456212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org holey_initial, 456312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DISABLE_ALLOCATION_SITES); 456412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallStub(&stub_holey); 456512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 456612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&normal_sequence); 456712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ArraySingleArgumentConstructorStub stub(masm->isolate(), 456812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org initial, 456912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DISABLE_ALLOCATION_SITES); 457012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallStub(&stub); 457112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (mode == DONT_OVERRIDE) { 457212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We are going to create a holey array, but our kind is non-holey. 457312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Fix kind and retry (only if we have an allocation site in the slot). 457412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a3, a3, Operand(1)); 457512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 457612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_debug_code) { 457712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a5, FieldMemOperand(a2, 0)); 457812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); 457912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Assert(eq, kExpectedAllocationSite, a5, Operand(at)); 458012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 458112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 458212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Save the resulting elements kind in type info. We can't just store a3 458312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // in the AllocationSite::transition_info field because elements kind is 458412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // restricted to a portion of the field...upper bits need to be left alone. 458512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 458612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, FieldMemOperand(a2, AllocationSite::kTransitionInfoOffset)); 458712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a4, a4, Operand(Smi::FromInt(kFastElementsKindPackedToHoley))); 458812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a4, FieldMemOperand(a2, AllocationSite::kTransitionInfoOffset)); 458912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 459012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 459112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&normal_sequence); 459212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int last_index = GetSequenceIndexFromFastElementsKind( 459312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TERMINAL_FAST_ELEMENTS_KIND); 459412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 0; i <= last_index; ++i) { 459512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 459612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ArraySingleArgumentConstructorStub stub(masm->isolate(), kind); 459712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallStub(&stub, eq, a3, Operand(kind)); 459812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 459912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 460012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If we reached this point there is a problem. 460112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Abort(kUnexpectedElementsKindInArrayConstructor); 460212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 460312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 460412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 460512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 460612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 460712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 460812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtemplate<class T> 460912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { 461012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int to_index = GetSequenceIndexFromFastElementsKind( 461112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TERMINAL_FAST_ELEMENTS_KIND); 461212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 0; i <= to_index; ++i) { 461312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 461412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org T stub(isolate, kind); 461512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stub.GetCode(); 461612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { 461712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org T stub1(isolate, kind, DISABLE_ALLOCATION_SITES); 461812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stub1.GetCode(); 461912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 462012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 462112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 462212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 462312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 462412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { 462512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( 462612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate); 462712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( 462812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate); 462912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( 463012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate); 463112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 463212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 463312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 463412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( 463512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Isolate* isolate) { 463612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS }; 463712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 0; i < 2; i++) { 463812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // For internal arrays we only need a few things. 463912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]); 464012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stubh1.GetCode(); 464112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]); 464212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stubh2.GetCode(); 464312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); 464412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stubh3.GetCode(); 464512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 464612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 464712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 464812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 464912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid ArrayConstructorStub::GenerateDispatchToArrayStub( 465012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MacroAssembler* masm, 465112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org AllocationSiteOverrideMode mode) { 4652fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org if (argument_count() == ANY) { 465312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label not_zero_case, not_one_case; 465412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(at, a0, a0); 465512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(¬_zero_case, ne, at, Operand(zero_reg)); 465612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 465712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 465812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_zero_case); 465912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(¬_one_case, gt, a0, Operand(1)); 466012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CreateArrayDispatchOneArgument(masm, mode); 466112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 466212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(¬_one_case); 466312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 4664fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org } else if (argument_count() == NONE) { 466512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 4666fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org } else if (argument_count() == ONE) { 466712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CreateArrayDispatchOneArgument(masm, mode); 4668fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org } else if (argument_count() == MORE_THAN_ONE) { 466912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 467012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 467112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 467212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 467312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 467412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 467512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 467612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid ArrayConstructorStub::Generate(MacroAssembler* masm) { 467712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------- S t a t e ------------- 4678fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org // -- a0 : argc (only if argument_count() == ANY) 467912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a1 : constructor 468012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a2 : AllocationSite or undefined 468112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- sp[0] : return address 468212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- sp[4] : last argument 468312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------------------------------- 468412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 468512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_debug_code) { 468612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The array construct code is only set for the global and natives 468712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // builtin Array functions which always have maps. 468812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 468912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Initial map for the builtin Array function should be a map. 469012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a4, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); 469112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Will both indicate a NULL and a Smi. 469212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiTst(a4, at); 469312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Assert(ne, kUnexpectedInitialMapForArrayFunction, 469412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org at, Operand(zero_reg)); 469512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a4, a4, a5); 469612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Assert(eq, kUnexpectedInitialMapForArrayFunction, 469712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a5, Operand(MAP_TYPE)); 469812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 469912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We should either have undefined in a2 or a valid AllocationSite 470012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ AssertUndefinedOrAllocationSite(a2, a4); 470112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 470212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 470312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label no_info; 470412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the elements kind and case on that. 470512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 470612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&no_info, eq, a2, Operand(at)); 470712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 470812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, FieldMemOperand(a2, AllocationSite::kTransitionInfoOffset)); 470912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiUntag(a3); 471012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 471112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ And(a3, a3, Operand(AllocationSite::ElementsKindBits::kMask)); 471212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); 471312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 471412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&no_info); 471512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); 471612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 471712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 471812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 471912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid InternalArrayConstructorStub::GenerateCase( 472012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MacroAssembler* masm, ElementsKind kind) { 472112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 472212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InternalArrayNoArgumentConstructorStub stub0(isolate(), kind); 472312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallStub(&stub0, lo, a0, Operand(1)); 472412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 472512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InternalArrayNArgumentsConstructorStub stubN(isolate(), kind); 472612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallStub(&stubN, hi, a0, Operand(1)); 472712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 472812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (IsFastPackedElementsKind(kind)) { 472912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We might need to create a holey array 473012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // look at the first argument. 473112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(at, MemOperand(sp, 0)); 473212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 473312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InternalArraySingleArgumentConstructorStub 473412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stub1_holey(isolate(), GetHoleyElementsKind(kind)); 473512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallStub(&stub1_holey, ne, at, Operand(zero_reg)); 473612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 473712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 473812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InternalArraySingleArgumentConstructorStub stub1(isolate(), kind); 473912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ TailCallStub(&stub1); 474012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 474112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 474212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 474312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid InternalArrayConstructorStub::Generate(MacroAssembler* masm) { 474412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------- S t a t e ------------- 474512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a0 : argc 474612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a1 : constructor 474712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- sp[0] : return address 474812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- sp[4] : last argument 474912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------------------------------- 475012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 475112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_debug_code) { 475212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The array construct code is only set for the global and natives 475312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // builtin Array functions which always have maps. 475412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 475512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Initial map for the builtin Array function should be a map. 475612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); 475712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Will both indicate a NULL and a Smi. 475812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ SmiTst(a3, at); 475912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Assert(ne, kUnexpectedInitialMapForArrayFunction, 476012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org at, Operand(zero_reg)); 476112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ GetObjectType(a3, a3, a4); 476212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Assert(eq, kUnexpectedInitialMapForArrayFunction, 476312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a4, Operand(MAP_TYPE)); 476412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 476512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 476612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Figure out the right elements kind. 476712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); 476812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 476912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load the map's "bit field 2" into a3. We only need the first byte, 477012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // but the following bit field extraction takes care of that anyway. 477112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ lbu(a3, FieldMemOperand(a3, Map::kBitField2Offset)); 477212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Retrieve elements_kind from bit field 2. 477312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ DecodeField<Map::ElementsKindBits>(a3); 477412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 477512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (FLAG_debug_code) { 477612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label done; 477712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&done, eq, a3, Operand(FAST_ELEMENTS)); 477812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Assert( 477912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org eq, kInvalidElementsKindForInternalArrayOrInternalPackedArray, 478012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org a3, Operand(FAST_HOLEY_ELEMENTS)); 478112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&done); 478212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 478312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 478412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Label fast_elements_case; 478512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Branch(&fast_elements_case, eq, a3, Operand(FAST_ELEMENTS)); 478612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateCase(masm, FAST_HOLEY_ELEMENTS); 478712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 478812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ bind(&fast_elements_case); 478912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GenerateCase(masm, FAST_ELEMENTS); 479012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 479112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 479212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 479312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid CallApiFunctionStub::Generate(MacroAssembler* masm) { 479412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------- S t a t e ------------- 479512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a0 : callee 479612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a4 : call_data 479712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a2 : holder 479812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a1 : api_function_address 479912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- cp : context 480012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- 480112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- sp[0] : last argument 480212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- ... 480312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- sp[(argc - 1)* 4] : first argument 480412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- sp[argc * 4] : receiver 480512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------------------------------- 480612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 480712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register callee = a0; 480812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register call_data = a4; 480912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register holder = a2; 481012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register api_function_address = a1; 481112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register context = cp; 481212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 4813fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org int argc = this->argc(); 4814fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org bool is_store = this->is_store(); 4815fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org bool call_data_undefined = this->call_data_undefined(); 481612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 481712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org typedef FunctionCallbackArguments FCA; 481812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 481912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(FCA::kContextSaveIndex == 6); 482012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(FCA::kCalleeIndex == 5); 482112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(FCA::kDataIndex == 4); 482212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(FCA::kReturnValueOffset == 3); 482312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 482412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(FCA::kIsolateIndex == 1); 482512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(FCA::kHolderIndex == 0); 482612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org STATIC_ASSERT(FCA::kArgsLength == 7); 482712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 482812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Save context, callee and call data. 482912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(context, callee, call_data); 483012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Load context from callee. 483112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ ld(context, FieldMemOperand(callee, JSFunction::kContextOffset)); 483212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 483312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Register scratch = call_data; 483412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!call_data_undefined) { 483512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 483612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 483712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Push return value and default return value. 483812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(scratch, scratch); 483912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(scratch, 484012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Operand(ExternalReference::isolate_address(isolate()))); 484112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Push isolate and holder. 484212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Push(scratch, holder); 484312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 484412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Prepare arguments. 484512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(scratch, sp); 484612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 484712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Allocate the v8::Arguments structure in the arguments' space since 484812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // it's not controlled by GC. 484912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kApiStackSpace = 4; 485012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 485112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FrameScope frame_scope(masm, StackFrame::MANUAL); 485212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ EnterExitFrame(false, kApiStackSpace); 485312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 4854e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!api_function_address.is(a0) && !scratch.is(a0)); 485512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a0 = FunctionCallbackInfo& 485612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Arguments is after the return address. 485712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a0, sp, Operand(1 * kPointerSize)); 485812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // FunctionCallbackInfo::implicit_args_ 485912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(scratch, MemOperand(a0, 0 * kPointerSize)); 486012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // FunctionCallbackInfo::values_ 486112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(at, scratch, Operand((FCA::kArgsLength - 1 + argc) * kPointerSize)); 486212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(at, MemOperand(a0, 1 * kPointerSize)); 486312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // FunctionCallbackInfo::length_ = argc 486412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ li(at, Operand(argc)); 486512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(at, MemOperand(a0, 2 * kPointerSize)); 486612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // FunctionCallbackInfo::is_construct_call = 0 486712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(zero_reg, MemOperand(a0, 3 * kPointerSize)); 486812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 486912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kStackUnwindSpace = argc + FCA::kArgsLength + 1; 487012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference thunk_ref = 487112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::invoke_function_callback(isolate()); 487212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 487312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org AllowExternalCallThatCantCauseGC scope(masm); 487412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MemOperand context_restore_operand( 487512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org fp, (2 + FCA::kContextSaveIndex) * kPointerSize); 487612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stores return the first js argument. 487712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int return_value_offset = 0; 487812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (is_store) { 487912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return_value_offset = 2 + FCA::kArgsLength; 488012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 488112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return_value_offset = 2 + FCA::kReturnValueOffset; 488212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 488312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MemOperand return_value_operand(fp, return_value_offset * kPointerSize); 488412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 488512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallApiFunctionAndReturn(api_function_address, 488612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org thunk_ref, 488712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kStackUnwindSpace, 488812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return_value_operand, 488912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &context_restore_operand); 489012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 489112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 489212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 489312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid CallApiGetterStub::Generate(MacroAssembler* masm) { 489412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------- S t a t e ------------- 489512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- sp[0] : name 489612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- sp[4 - kArgsLength*4] : PropertyCallbackArguments object 489712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- ... 489812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // -- a2 : api_function_address 489912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ----------------------------------- 490012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 49016313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org Register api_function_address = ApiGetterDescriptor::function_address(); 49026313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org DCHECK(api_function_address.is(a2)); 490312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 490412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ mov(a0, sp); // a0 = Handle<Name> 490512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a1, a0, Operand(1 * kPointerSize)); // a1 = PCA 490612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 490712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kApiStackSpace = 1; 490812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FrameScope frame_scope(masm, StackFrame::MANUAL); 490912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ EnterExitFrame(false, kApiStackSpace); 491012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 491112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Create PropertyAccessorInfo instance on the stack above the exit frame with 491212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a1 (internal::Object** args_) as the data. 491312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ sd(a1, MemOperand(sp, 1 * kPointerSize)); 491412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ Daddu(a1, sp, Operand(1 * kPointerSize)); // a1 = AccessorInfo& 491512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 491612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; 491712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 491812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference thunk_ref = 491912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::invoke_accessor_getter_callback(isolate()); 492012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org __ CallApiFunctionAndReturn(api_function_address, 492112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org thunk_ref, 492212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org kStackUnwindSpace, 492312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MemOperand(fp, 6 * kPointerSize), 492412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org NULL); 492512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 492612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 492712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 492812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef __ 492912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 493012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} } // namespace v8::internal 493112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 493212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif // V8_TARGET_ARCH_MIPS64 4933