1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved. 2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be 3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file. 4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC 6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 73b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/code-stubs.h" 83b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/api-arguments.h" 9958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/base/bits.h" 10958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/bootstrapper.h" 11958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/codegen.h" 12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/handler-compiler.h" 13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/ic.h" 14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ic/stub-cache.h" 15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/isolate.h" 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ppc/code-stubs-ppc.h" 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/jsregexp.h" 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/regexp-macro-assembler.h" 19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h" 20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 { 22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal { 23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define __ ACCESS_MASM(masm) 25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) { 2713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2)); 2813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ StorePX(r4, MemOperand(sp, r0)); 2913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ push(r4); 3013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ push(r5); 3113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ addi(r3, r3, Operand(3)); 3213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ TailCallRuntime(Runtime::kNewArray); 33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, 36109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Condition cond); 37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs, 38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs, Label* lhs_not_nan, 39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* slow, bool strict); 40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs, 41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs); 42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm, 45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference miss) { 46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Update the static counter each time a new code stub is generated. 47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate()->counters()->code_stubs()->Increment(); 48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor(); 50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int param_count = descriptor.GetRegisterParameterCount(); 51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call the runtime system in a fresh internal frame. 53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(param_count == 0 || 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch r3.is(descriptor.GetRegisterParameter(param_count - 1))); 56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Push arguments 57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (int i = 0; i < param_count; ++i) { 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(descriptor.GetRegisterParameter(i)); 59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallExternalReference(miss, param_count); 61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid DoubleToIStub::Generate(MacroAssembler* masm) { 68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label out_of_range, only_low, negate, done, fastpath_done; 69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register input_reg = source(); 70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register result_reg = destination(); 71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(is_truncating()); 72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int double_offset = offset(); 74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Immediate values for this stub fit in instructions, so it's safe to use ip. 76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch = GetRegisterThatIsNotOneOf(input_reg, result_reg); 77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch_low = 78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch); 79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch_high = 80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low); 81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DoubleRegister double_scratch = kScratchDoubleReg; 82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(scratch); 84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Account for saved regs if input is sp. 85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (input_reg.is(sp)) double_offset += kPointerSize; 86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!skip_fastpath()) { 88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load double input. 89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(double_scratch, MemOperand(input_reg, double_offset)); 90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Do fast-path convert from double to int. 92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ConvertDoubleToInt64(double_scratch, 93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if !V8_TARGET_ARCH_PPC64 94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scratch, 95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif 96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier result_reg, d0); 97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Test for overflow 99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64 100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TestIfInt32(result_reg, r0); 101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#else 102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TestIfInt32(scratch, result_reg, r0); 103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif 104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&fastpath_done); 105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(scratch_high, scratch_low); 108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Account for saved regs if input is sp. 109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (input_reg.is(sp)) double_offset += 2 * kPointerSize; 110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwz(scratch_high, 112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemOperand(input_reg, double_offset + Register::kExponentOffset)); 113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwz(scratch_low, 114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemOperand(input_reg, double_offset + Register::kMantissaOffset)); 115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ExtractBitMask(scratch, scratch_high, HeapNumber::kExponentMask); 117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load scratch with exponent - 1. This is faster than loading 118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // with exponent because Bias + 1 = 1024 which is a *PPC* immediate value. 119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(HeapNumber::kExponentBias + 1 == 1024); 120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subi(scratch, scratch, Operand(HeapNumber::kExponentBias + 1)); 121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If exponent is greater than or equal to 84, the 32 less significant 122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits), 123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the result is 0. 124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare exponent with 84 (compare exponent - 1 with 83). 125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(scratch, Operand(83)); 126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bge(&out_of_range); 127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If we reach this code, 31 <= exponent <= 83. 129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // So, we don't have to handle cases where 0 <= exponent <= 20 for 130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // which we would need to shift right the high part of the mantissa. 131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Scratch contains exponent - 1. 132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load scratch with 52 - exponent (load with 51 - (exponent - 1)). 133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subfic(scratch, scratch, Operand(51)); 134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(scratch, Operand::Zero()); 135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ble(&only_low); 136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 21 <= exponent <= 51, shift scratch_low and scratch_high 137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // to generate the result. 138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ srw(scratch_low, scratch_low, scratch); 139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Scratch contains: 52 - exponent. 140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We needs: exponent - 20. 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20. 142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subfic(scratch, scratch, Operand(32)); 143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ExtractBitMask(result_reg, scratch_high, HeapNumber::kMantissaMask); 144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Set the implicit 1 before the mantissa part in scratch_high. 145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(HeapNumber::kMantissaBitsInTopWord >= 16); 146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ oris(result_reg, result_reg, 147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(1 << ((HeapNumber::kMantissaBitsInTopWord) - 16))); 148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ slw(r0, result_reg, scratch); 149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(result_reg, scratch_low, r0); 150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&negate); 151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&out_of_range); 153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(result_reg, Operand::Zero()); 154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&done); 155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&only_low); 157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 52 <= exponent <= 83, shift only scratch_low. 158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // On entry, scratch contains: 52 - exponent. 159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ neg(scratch, scratch); 160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ slw(result_reg, scratch_low, scratch); 161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&negate); 163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If input was positive, scratch_high ASR 31 equals 0 and 164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // scratch_high LSR 31 equals zero. 165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // New result = (result eor 0) + 0 = result. 166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If the input was negative, we have to negate the result. 167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1. 168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // New result = (result eor 0xffffffff) + 1 = 0 - result. 169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ srawi(r0, scratch_high, 31); 170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64 171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ srdi(r0, r0, Operand(32)); 172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif 173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ xor_(result_reg, result_reg, r0); 174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ srwi(r0, scratch_high, Operand(31)); 175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(result_reg, result_reg, r0); 176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&done); 178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Pop(scratch_high, scratch_low); 179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&fastpath_done); 181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(scratch); 182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Handle the case where the lhs and rhs are the same object. 188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Equality is almost reflexive (everything but NaN), so this is a test 189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// for "identity and not NaN". 190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, 191109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Condition cond) { 192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label not_identical; 193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label heap_number, return_equal; 194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r3, r4); 195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(¬_identical); 196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), 198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // so we do the second best thing - test it ourselves. 199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // They are both equal and they are not both Smis so both of them are not 200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Smis. If it's not a heap number, then return equal. 201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond == lt || cond == gt) { 202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call runtime on identical JSObjects. 203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r3, r7, r7, FIRST_JS_RECEIVER_TYPE); 204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bge(slow); 205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call runtime on identical symbols since we need to throw a TypeError. 206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(r7, Operand(SYMBOL_TYPE)); 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(slow); 208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE); 210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&heap_number); 211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Comparing JS objects with <=, >= is complicated. 212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond != eq) { 213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(r7, Operand(FIRST_JS_RECEIVER_TYPE)); 214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bge(slow); 215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call runtime on identical symbols since we need to throw a TypeError. 216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(r7, Operand(SYMBOL_TYPE)); 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(slow); 218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Normally here we fall through to return_equal, but undefined is 219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // special: (undefined == undefined) == true, but 220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (undefined <= undefined) == false! See ECMAScript 11.8.5. 221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond == le || cond == ge) { 222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r7, Operand(ODDBALL_TYPE)); 223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&return_equal); 224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); 225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r3, r5); 226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&return_equal); 227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond == le) { 228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // undefined <= undefined should fail. 229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(GREATER)); 230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // undefined >= undefined should fail. 232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(LESS)); 233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&return_equal); 240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond == lt) { 241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(GREATER)); // Things aren't less than themselves. 242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (cond == gt) { 243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(LESS)); // Things aren't greater than themselves. 244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(EQUAL)); // Things are <=, >=, ==, === themselves. 246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For less and greater we don't have to check for NaN since the result of 250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // x < x is false regardless. For the others here is some code to check 251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // for NaN. 252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond != lt && cond != gt) { 253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&heap_number); 254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // It is a heap number, so return non-equal if it's NaN and equal if it's 255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // not NaN. 256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The representation of NaN values has all exponent bits (52..62) set, 258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // and not all mantissa bits (0..51) clear. 259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Read top bits of double representation (second word of value). 260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwz(r5, FieldMemOperand(r3, HeapNumber::kExponentOffset)); 261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Test that exponent bits are all set. 262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(HeapNumber::kExponentMask == 0x7ff00000u); 263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ExtractBitMask(r6, r5, HeapNumber::kExponentMask); 264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpli(r6, Operand(0x7ff)); 265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&return_equal); 266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Shift out flag and all exponent bits, retaining only mantissa. 268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ slwi(r5, r5, Operand(HeapNumber::kNonMantissaBitsInTopWord)); 269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Or with all low-bits of mantissa. 270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwz(r6, FieldMemOperand(r3, HeapNumber::kMantissaOffset)); 271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(r3, r6, r5); 272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r3, Operand::Zero()); 273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For equal we already have the right value in r3: Return zero (equal) 274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // if all bits in mantissa are zero (it's an Infinity) and non-zero if 275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // not (it's a NaN). For <= and >= we need to load r0 with the failing 276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // value if it's a NaN. 277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond != eq) { 278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r4, Operand((cond == le) ? GREATER : LESS)); 280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, r3, r3, r4); 281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // All-zero means Infinity means equal. 283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(eq); 284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (cond == le) { 285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(GREATER)); // NaN <= NaN should fail. 286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(LESS)); // NaN >= NaN should fail. 288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // No fall through here. 294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_identical); 296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// See comment at call site. 300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs, 301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs, Label* lhs_not_nan, 302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* slow, bool strict) { 303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label rhs_is_smi; 306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(rhs, &rhs_is_smi); 307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Lhs is a Smi. Check whether the rhs is a heap number. 309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(rhs, r6, r7, HEAP_NUMBER_TYPE); 310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (strict) { 311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If rhs is not a number and lhs is a Smi then strict equality cannot 312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // succeed. Return non-equal 313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If rhs is r3 then there is already a non zero value in it. 314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!rhs.is(r3)) { 315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label skip; 316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&skip); 317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(NOT_EQUAL)); 318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&skip); 320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(ne); 322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Smi compared non-strictly with a non-Smi non-heap-number. Call 325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the runtime. 326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(slow); 327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Lhs is a smi, rhs is a number. 330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Convert lhs to a double in d7. 331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToDouble(d7, lhs); 332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the double from rhs, tagged HeapNumber r3, to d6. 333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We now have both loaded as doubles but we can skip the lhs nan check 336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // since it's a smi. 337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(lhs_not_nan); 338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&rhs_is_smi); 340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Rhs is a smi. Check whether the non-smi lhs is a heap number. 341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(lhs, r7, r7, HEAP_NUMBER_TYPE); 342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (strict) { 343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If lhs is not a number and rhs is a smi then strict equality cannot 344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // succeed. Return non-equal. 345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If lhs is r3 then there is already a non zero value in it. 346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!lhs.is(r3)) { 347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label skip; 348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&skip); 349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(NOT_EQUAL)); 350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&skip); 352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(ne); 354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Smi compared non-strictly with a non-smi non-heap-number. Call 357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the runtime. 358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(slow); 359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Rhs is a smi, lhs is a heap number. 362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the double from lhs, tagged HeapNumber r4, to d7. 363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Convert rhs to a double in d6. 365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToDouble(d6, rhs); 366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Fall through to both_loaded_as_doubles. 367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// See comment at call site. 371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs, 372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs) { 373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If either operand is a JS object or an oddball value, then they are 376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // not equal since their pointers are different. 377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // There is no test for undetectability in strict equality. 378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label first_non_object; 380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get the type of the first operand into r5 and compare it with 381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // FIRST_JS_RECEIVER_TYPE. 382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(rhs, r5, r5, FIRST_JS_RECEIVER_TYPE); 383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(&first_non_object); 384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return non-zero (r3 is not zero) 386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label return_not_equal; 387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&return_not_equal); 388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&first_non_object); 391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for oddballs: true, false, null, undefined. 392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r5, Operand(ODDBALL_TYPE)); 393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&return_not_equal); 394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(lhs, r6, r6, FIRST_JS_RECEIVER_TYPE); 396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bge(&return_not_equal); 397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for oddballs: true, false, null, undefined. 399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r6, Operand(ODDBALL_TYPE)); 400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&return_not_equal); 401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Now that we have the types we might as well check for 403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // internalized-internalized. 404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(r5, r5, r6); 406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r5, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&return_not_equal, cr0); 408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// See comment at call site. 412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, Register lhs, 413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs, 414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* both_loaded_as_doubles, 415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* not_heap_numbers, Label* slow) { 416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(rhs, r6, r5, HEAP_NUMBER_TYPE); 419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(not_heap_numbers); 420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r5, FieldMemOperand(lhs, HeapObject::kMapOffset)); 421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r5, r6); 422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(slow); // First was a heap number, second wasn't. Go slow case. 423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Both are heap numbers. Load them up then jump to the code we have 425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // for that. 426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(both_loaded_as_doubles); 430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// Fast negative check for internalized-to-internalized equality or receiver 4333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// equality. Also handles the undetectable receiver to null/undefined 4343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// comparison. 435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, 436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register lhs, Register rhs, 437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* possible_strings, 438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label* runtime_call) { 439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5 is object type of rhs. 4423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label object_test, return_equal, return_unequal, undetectable; 443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r5, Operand(kIsNotStringMask)); 445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&object_test, cr0); 446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r5, Operand(kIsNotInternalizedMask)); 447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(possible_strings, cr0); 448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(lhs, r6, r6, FIRST_NONSTRING_TYPE); 449109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bge(runtime_call); 450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r6, Operand(kIsNotInternalizedMask)); 451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(possible_strings, cr0); 452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 453109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Both are internalized. We already checked they weren't the same pointer so 454109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // they are not equal. Return non-equal by returning the non-zero object 455109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // pointer in r3. 456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&object_test); 459109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r5, FieldMemOperand(lhs, HeapObject::kMapOffset)); 460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r6, FieldMemOperand(rhs, HeapObject::kMapOffset)); 461109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lbz(r7, FieldMemOperand(r5, Map::kBitFieldOffset)); 462109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lbz(r8, FieldMemOperand(r6, Map::kBitFieldOffset)); 463109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andi(r0, r7, Operand(1 << Map::kIsUndetectable)); 464109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&undetectable, cr0); 465109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andi(r0, r8, Operand(1 << Map::kIsUndetectable)); 466109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&return_unequal, cr0); 467109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 468109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareInstanceType(r5, r5, FIRST_JS_RECEIVER_TYPE); 469109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ blt(runtime_call); 470109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareInstanceType(r6, r6, FIRST_JS_RECEIVER_TYPE); 471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ blt(runtime_call); 472109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 473109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&return_unequal); 474109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Return non-equal by returning the non-zero object pointer in r3. 475109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 476109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 477109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&undetectable); 478109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andi(r0, r8, Operand(1 << Map::kIsUndetectable)); 479109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&return_unequal, cr0); 4803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // If both sides are JSReceivers, then the result is false according to 4823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // the HTML specification, which says that only comparisons with null or 4833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // undefined are affected by special casing for document.all. 4843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CompareInstanceType(r5, r5, ODDBALL_TYPE); 4853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ beq(&return_equal); 4863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CompareInstanceType(r6, r6, ODDBALL_TYPE); 4873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bne(&return_unequal); 4883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bind(&return_equal); 490109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ li(r3, Operand(EQUAL)); 491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, 496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch, 497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompareICState::State expected, 498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* fail) { 499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label ok; 500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (expected == CompareICState::SMI) { 501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(input, fail); 502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (expected == CompareICState::NUMBER) { 503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(input, &ok); 504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, 505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DONT_DO_SMI_CHECK); 506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We could be strict about internalized/non-internalized here, but as long as 508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // hydrogen doesn't care, the stub doesn't have to care either. 509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&ok); 510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// On entry r4 and r5 are the values to be compared. 514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// On exit r3 is 0, positive or negative to indicate the result of 515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the comparison. 516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateGeneric(MacroAssembler* masm) { 517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register lhs = r4; 518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs = r3; 519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Condition cc = GetCondition(); 520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompareICStub_CheckInputType(masm, lhs, r5, left(), &miss); 523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompareICStub_CheckInputType(masm, rhs, r6, right(), &miss); 524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label slow; // Call builtin. 526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label not_smis, both_loaded_as_doubles, lhs_not_nan; 527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label not_two_smis, smi_done; 529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(r5, r4, r3); 530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r5, ¬_two_smis); 531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r4); 532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r3); 533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ sub(r3, r4, r3); 534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_two_smis); 536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // NOTICE! This code is only reached after a smi-fast-case check, so 538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // it is certain that at least one operand isn't a smi. 539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Handle the case where the objects are identical. Either returns the answer 541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // or goes to slow. Only falls through if the objects were not identical. 542109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitIdenticalObjectComparison(masm, &slow, cc); 543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If either is a Smi (we know that not both are), then they can only 545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // be strictly equal if the other is a HeapNumber. 546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 547c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_EQ(static_cast<Smi*>(0), Smi::kZero); 548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(r5, lhs, rhs); 549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r5, ¬_smis); 550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // One operand is a smi. EmitSmiNonsmiComparison generates code that can: 551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 1) Return the answer. 552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 2) Go to slow. 553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 3) Fall through to both_loaded_as_doubles. 554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 4) Jump to lhs_not_nan. 555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // In cases 3 and 4 we have found out we were dealing with a number-number 556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // comparison. The double values of the numbers have been loaded 557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // into d7 and d6. 558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict()); 559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&both_loaded_as_doubles); 561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The arguments have been converted to doubles and stored in d6 and d7 562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&lhs_not_nan); 563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label no_nan; 564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fcmpu(d7, d6); 565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label nan, equal, less_than; 567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bunordered(&nan); 568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(EQUAL == 0); 570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r4, Operand(GREATER)); 571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r5, Operand(LESS)); 572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, r3, r0, r4); 573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(lt, r3, r5, r3); 574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&equal); 577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blt(&less_than); 578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(GREATER)); 579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&equal); 581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(EQUAL)); 582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&less_than); 584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(LESS)); 585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&nan); 589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If one of the sides was a NaN then the v flag is set. Load r3 with 590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // whatever it takes to make the comparison fail, since comparisons with NaN 591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // always fail. 592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cc == lt || cc == le) { 593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(GREATER)); 594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(LESS)); 596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_smis); 600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // At this point we know we are dealing with two different objects, 601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // and neither of them is a Smi. The objects are in rhs_ and lhs_. 602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (strict()) { 603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // This returns non-equal for some object types, or falls through if it 604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // was not lucky. 605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitStrictTwoHeapObjectCompare(masm, lhs, rhs); 606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label check_for_internalized_strings; 609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label flat_string_check; 610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for heap-number-heap-number comparison. Can jump to slow case, 611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // or load both doubles into r3, r4, r5, r6 and jump to the code that handles 612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // that case. If the inputs are not doubles then jumps to 613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // check_for_internalized_strings. 614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // In this case r5 will contain the type of rhs_. Never falls through. 615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitCheckForTwoHeapNumbers(masm, lhs, rhs, &both_loaded_as_doubles, 616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &check_for_internalized_strings, 617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &flat_string_check); 618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&check_for_internalized_strings); 620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // In the strict case the EmitStrictTwoHeapObjectCompare already took care of 621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // internalized strings. 622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cc == eq && !strict()) { 623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Returns an answer for two internalized strings or two detectable objects. 624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Otherwise jumps to string case or not both strings case. 625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Assumes that r5 is the type of rhs_ on entry. 626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitCheckForInternalizedStringsOrObjects(masm, lhs, rhs, &flat_string_check, 627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &slow); 628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for both being sequential one-byte strings, 631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // and inline if that is the case. 632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&flat_string_check); 633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNonSmisNotBothSequentialOneByteStrings(lhs, rhs, r5, r6, &slow); 635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r5, 637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r6); 638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cc == eq) { 639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringHelper::GenerateFlatOneByteStringEquals(masm, lhs, rhs, r5, r6); 640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringHelper::GenerateCompareFlatOneByteStrings(masm, lhs, rhs, r5, r6, r7); 642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Never falls through to here. 644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&slow); 646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cc == eq) { 648109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 65062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(cp); 65162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(strict() ? isolate()->builtins()->StrictEqual() 65262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : isolate()->builtins()->Equal(), 65362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelocInfo::CODE_TARGET); 65462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Pop(cp); 655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Turn true into 0 and false into some non-zero value. 657109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(EQUAL == 0); 658109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r4, Heap::kTrueValueRootIndex); 659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ sub(r3, r3, r4); 660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(lhs, rhs); 663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int ncr; // NaN compare result 664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cc == lt || cc == le) { 665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ncr = GREATER; 666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(cc == gt || cc == ge); // remaining cases 668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ncr = LESS; 669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(ncr)); 671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r3); 672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // tagged as a small integer. 675109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallRuntime(Runtime::kCompare); 676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We don't allow a GC during a store buffer overflow so there is no need to 685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // store the registers in any particular way, but we do have to store and 686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // restore them. 687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPush(kJSCallerSaved | r0.bit()); 689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (save_doubles()) { 690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ MultiPushDoubles(kCallerSavedDoubles); 691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int argument_count = 1; 693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int fp_argument_count = 0; 694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register scratch = r4; 695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AllowExternalCallThatCantCauseGC scope(masm); 697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); 698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(ExternalReference::isolate_address(isolate()))); 699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallCFunction(ExternalReference::store_buffer_overflow_function(isolate()), 700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier argument_count); 701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (save_doubles()) { 702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ MultiPopDoubles(kCallerSavedDoubles); 703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPop(kJSCallerSaved | r0.bit()); 705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtlr(r0); 706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreRegistersStateStub::Generate(MacroAssembler* masm) { 711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ PushSafepointRegisters(); 712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blr(); 713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RestoreRegistersStateStub::Generate(MacroAssembler* masm) { 717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ PopSafepointRegisters(); 718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blr(); 719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 720958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 721958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MathPowStub::Generate(MacroAssembler* masm) { 723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register exponent = MathPowTaggedDescriptor::exponent(); 724958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(exponent.is(r5)); 725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const DoubleRegister double_base = d1; 726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const DoubleRegister double_exponent = d2; 727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const DoubleRegister double_result = d3; 728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const DoubleRegister double_scratch = d0; 729958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register scratch = r11; 730958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register scratch2 = r10; 731958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 732958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label call_runtime, done, int_exponent; 733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (exponent_type() == TAGGED) { 734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Base is already in double_base. 735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 736958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(double_exponent, 738958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(exponent, HeapNumber::kValueOffset)); 739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (exponent_type() != INTEGER) { 742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Detect integer exponents stored as double. 743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TryDoubleToInt32Exact(scratch, double_exponent, scratch2, 744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier double_scratch); 745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&int_exponent); 746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AllowExternalCallThatCantCauseGC scope(masm); 751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ PrepareCallCFunction(0, 2, scratch); 752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MovToFloatParameters(double_base, double_exponent); 753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallCFunction( 754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::power_double_double_function(isolate()), 0, 2); 755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(r0); 757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtlr(r0); 758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MovFromFloatResult(double_result); 759958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&done); 760958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 761958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 762958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Calculate power with integer exponent. 763958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&int_exponent); 764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 765958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get two copies of exponent in the registers scratch and exponent. 766958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (exponent_type() == INTEGER) { 767958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(scratch, exponent); 768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Exponent has previously been stored into scratch as untagged integer. 770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(exponent, scratch); 771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fmr(double_scratch, double_base); // Back up base. 773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(scratch2, Operand(1)); 774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ConvertIntToDouble(scratch2, double_result); 775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get absolute value of exponent. 777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(scratch, Operand::Zero()); 778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ neg(scratch2, scratch); 780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(lt, scratch, scratch2, scratch); 781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label positive_exponent; 783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bge(&positive_exponent); 784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ neg(scratch, scratch); 785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&positive_exponent); 786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label while_true, no_carry, loop_end; 789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&while_true); 790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(scratch2, scratch, Operand(1)); 791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&no_carry, cr0); 792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fmul(double_result, double_result, double_scratch); 793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&no_carry); 794f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ ShiftRightImm(scratch, scratch, Operand(1), SetRC); 795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&loop_end, cr0); 796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fmul(double_scratch, double_scratch, double_scratch); 797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&while_true); 798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&loop_end); 799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(exponent, Operand::Zero()); 801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bge(&done); 802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 803958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(scratch2, Operand(1)); 804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ConvertIntToDouble(scratch2, double_scratch); 805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fdiv(double_result, double_scratch, double_result); 806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Test whether result is zero. Bail out to check for subnormal result. 807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. 808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fcmpu(double_result, kDoubleRegZero); 809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&done); 810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // double_exponent may not containe the exponent value if the input was a 811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // smi. We set it with exponent value before bailing out. 812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ConvertIntToDouble(exponent, double_exponent); 813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Returning or bailing out. 815f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mflr(r0); 816f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(r0); 817f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 818f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 819f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PrepareCallCFunction(0, 2, scratch); 820f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ MovToFloatParameters(double_base, double_exponent); 821f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CallCFunction( 822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ExternalReference::power_double_double_function(isolate()), 0, 2); 823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 824f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ pop(r0); 825f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mtlr(r0); 826f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ MovFromFloatResult(double_result); 827f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 828f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&done); 829f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Ret(); 830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool CEntryStub::NeedsImmovableCode() { return true; } 834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 837958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CEntryStub::GenerateAheadOfTime(isolate); 838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 839958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 84013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate); 841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CreateWeakCellStub::GenerateAheadOfTime(isolate); 843958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier BinaryOpICStub::GenerateAheadOfTime(isolate); 844958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreRegistersStateStub::GenerateAheadOfTime(isolate); 845958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier RestoreRegistersStateStub::GenerateAheadOfTime(isolate); 846958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StoreFastElementStub::GenerateAheadOfTime(isolate); 848958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 849958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 850958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 851958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { 852958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreRegistersStateStub stub(isolate); 853958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub.GetCode(); 854958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 855958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 856958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 857958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RestoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { 858958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier RestoreRegistersStateStub stub(isolate); 859958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub.GetCode(); 860958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 861958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 862958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 863958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CodeStub::GenerateFPStubs(Isolate* isolate) { 864958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Generate if not already in cache. 865958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SaveFPRegsMode mode = kSaveFPRegs; 866958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CEntryStub(isolate, 1, mode).GetCode(); 867958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreBufferOverflowStub(isolate, mode).GetCode(); 868958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 869958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 870958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 871958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 872958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CEntryStub stub(isolate, 1, kDontSaveFPRegs); 873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub.GetCode(); 874958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 875958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 876958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 877958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CEntryStub::Generate(MacroAssembler* masm) { 878958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Called from JavaScript; parameters are on stack as if calling JS function. 879958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: number of arguments including receiver 880958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: pointer to builtin function 881958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // fp: frame pointer (restored after C call) 882958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // sp: stack pointer (restored as callee's sp after C call) 883958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // cp: current context (C callee-saved) 884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If argv_in_register(): 886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r5: pointer to the first argument 887958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ProfileEntryHookStub::MaybeCallEntryHook(masm); 888958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 889958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r15, r4); 890958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (argv_in_register()) { 892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Move argv into the correct register. 893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r4, r5); 894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compute the argv pointer. 896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ShiftLeftImm(r4, r3, Operand(kPointerSizeLog2)); 897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(r4, r4, sp); 898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ subi(r4, r4, Operand(kPointerSize)); 899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 900958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Enter the exit frame that transitions from JavaScript to C++. 902958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameScope scope(masm, StackFrame::MANUAL); 903958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 904958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Need at least one extra slot for return address location. 905958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int arg_stack_space = 1; 906958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Pass buffer for return value on stack if necessary 908109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch bool needs_return_buffer = 909109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch result_size() > 2 || 910109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch (result_size() == 2 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS); 911109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (needs_return_buffer) { 912109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch arg_stack_space += result_size(); 913958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 914958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 915f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterExitFrame(save_doubles(), arg_stack_space, is_builtin_exit() 916f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ? StackFrame::BUILTIN_EXIT 917f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch : StackFrame::EXIT); 918958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 919958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Store a copy of argc in callee-saved registers for later. 920958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r14, r3); 921958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3, r14: number of arguments including receiver (C callee-saved) 923958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: pointer to the first argument 924958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r15: pointer to builtin function (C callee-saved) 925958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 926958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Result returned in registers or stack, depending on result size and ABI. 927958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 928958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register isolate_reg = r5; 929109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (needs_return_buffer) { 930109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The return value is a non-scalar value. 931958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Use frame storage reserved by calling function to pass return 932958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // buffer as implicit first argument. 933958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r5, r4); 934958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r4, r3); 935958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize)); 936958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate_reg = r6; 937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 938958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 939958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call C built-in. 940958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate()))); 941958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register target = r15; 943109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (ABI_USES_FUNCTION_DESCRIPTORS) { 944109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // AIX/PPC64BE Linux use a function descriptor. 945109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize)); 946109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ip, MemOperand(r15, 0)); // Instruction address 947109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch target = ip; 948109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (ABI_CALL_VIA_IP) { 949109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Move(ip, r15); 950109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch target = ip; 951109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 952958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 953958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // To let the GC traverse the return address of the exit frames, we need to 954958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // know where the return address is. The CEntryStub is unmovable, so 955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // we can store the address on the stack to be able to find it again and 956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // we never have to restore it, because it will not change. 957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label after_call; 958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov_label_addr(r0, &after_call); 959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); 960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Call(target); 961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&after_call); 962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If return value is on the stack, pop it to registers. 964109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (needs_return_buffer) { 965109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (result_size() > 2) __ LoadP(r5, MemOperand(r3, 2 * kPointerSize)); 966958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r4, MemOperand(r3, kPointerSize)); 967958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, MemOperand(r3)); 968958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 969958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 970958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check result for exception sentinel. 971958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label exception_returned; 972958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareRoot(r3, Heap::kExceptionRootIndex); 973958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&exception_returned); 974958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 975958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that there is no pending exception, otherwise we 976958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // should have returned the exception sentinel. 977958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (FLAG_debug_code) { 978958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label okay; 979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_exception_address( 980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingExceptionAddress, isolate()); 981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 982109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(r6, Operand(pending_exception_address)); 983109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r6, MemOperand(r6)); 984109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); 985958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Cannot use check here as it attempts to generate call into runtime. 986958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&okay); 987958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ stop("Unexpected pending exception"); 988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&okay); 989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 990958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 991958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Exit C frame and return. 992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3:r4: result 993958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // sp: stack pointer 994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // fp: frame pointer 995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register argc; 996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (argv_in_register()) { 997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We don't want to pop arguments so set argc to no_reg. 998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch argc = no_reg; 999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r14: still holds argc (callee-saved). 1001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch argc = r14; 1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LeaveExitFrame(save_doubles(), argc, true); 1004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blr(); 1005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Handling of exception. 1007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&exception_returned); 1008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_handler_context_address( 1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingHandlerContextAddress, isolate()); 1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_handler_code_address( 1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingHandlerCodeAddress, isolate()); 1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_handler_offset_address( 1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingHandlerOffsetAddress, isolate()); 1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_handler_fp_address( 1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingHandlerFPAddress, isolate()); 1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_handler_sp_address( 1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingHandlerSPAddress, isolate()); 1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Ask the runtime for help to determine the handler. This will set r3 to 1021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // contain the current pending exception, don't clobber it. 1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler, 1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate()); 1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PrepareCallCFunction(3, 0, r3); 1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand::Zero()); 1028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r4, Operand::Zero()); 1029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r5, Operand(ExternalReference::isolate_address(isolate()))); 1030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallCFunction(find_handler, 3); 1031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1032958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Retrieve the handler context, SP and FP. 1034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(cp, Operand(pending_handler_context_address)); 1035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(cp, MemOperand(cp)); 1036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(sp, Operand(pending_handler_sp_address)); 1037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(sp, MemOperand(sp)); 1038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(fp, Operand(pending_handler_fp_address)); 1039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(fp, MemOperand(fp)); 1040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the handler is a JS frame, restore the context to the frame. Note that 1042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the context will be set to (cp == 0) for non-JS frames. 1043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label skip; 1044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(cp, Operand::Zero()); 1045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&skip); 1046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&skip); 1048958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compute the handler entry address and jump to it. 1050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ConstantPoolUnavailableScope constant_pool_unavailable(masm); 1051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r4, Operand(pending_handler_code_address)); 1052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r4, MemOperand(r4)); 1053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r5, Operand(pending_handler_offset_address)); 1054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r5, MemOperand(r5)); 1055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addi(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start 1056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_enable_embedded_constant_pool) { 1057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(r4); 1058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(ip, r4, r5); 1060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(ip); 1061958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1062958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1063958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1064958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid JSEntryStub::Generate(MacroAssembler* masm) { 1065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: code entry 1066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: function 1067958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: receiver 1068958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: argc 1069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // [sp+0]: argv 1070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label invoke, handler_entry, exit; 1072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Called from C 1074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ function_descriptor(); 1075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ProfileEntryHookStub::MaybeCallEntryHook(masm); 1077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // PPC LINUX ABI: 1079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // preserve LR in pre-reserved slot in caller's frame 1080958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 1081958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize)); 1082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Save callee saved registers on the stack. 1084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPush(kCalleeSaved); 1085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Save callee-saved double registers. 1087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ MultiPushDoubles(kCalleeSavedDoubles); 1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Set up the reserved register for 0.0. 1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadDoubleLiteral(kDoubleRegZero, 0.0, r0); 1090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Push a frame with special values setup to mark it as an entry frame. 1092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: code entry 1093958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: function 1094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: receiver 1095958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: argc 1096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r7: argv 1097958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r0, Operand(-1)); // Push a bad frame pointer to fail if it is used. 1098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 1099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_enable_embedded_constant_pool) { 1100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(kConstantPoolRegister, Operand::Zero()); 1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(kConstantPoolRegister); 1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 110362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StackFrame::Type marker = type(); 110462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(r0, Operand(StackFrame::TypeToMarker(marker))); 1105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 1106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 1107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Save copies of the top frame descriptor on the stack. 1108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 1109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r0, MemOperand(r8)); 1110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 1111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Set up frame pointer for the frame to be pushed. 1113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 1114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If this is the outermost JS call, set js_entry_sp value. 1116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label non_outermost_js; 1117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate()); 1118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r8, Operand(ExternalReference(js_entry_sp))); 1119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r9, MemOperand(r8)); 1120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r9, Operand::Zero()); 1121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&non_outermost_js); 1122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(fp, MemOperand(r8)); 112362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(ip, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME)); 1124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label cont; 1125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&cont); 1126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&non_outermost_js); 112762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(ip, Operand(StackFrame::INNER_JSENTRY_FRAME)); 1128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&cont); 1129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(ip); // frame-type 1130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Jump to a faked try block that does the invoke, with a faked catch 1132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // block that sets the pending exception. 1133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&invoke); 1134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&handler_entry); 1136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier handler_offset_ = handler_entry.pos(); 1137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Caught exception: Store result (exception) in the pending exception 1138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // field in the JSEnv and return a failure sentinel. Coming in here the 1139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // fp will be invalid because the PushStackHandler below sets it to 0 to 1140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // signal the existence of the JSEntry frame. 1141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate()))); 1143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r3, MemOperand(ip)); 1145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(r3, Heap::kExceptionRootIndex); 1146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&exit); 1147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Invoke: Link this frame into the handler chain. 1149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&invoke); 1150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Must preserve r3-r7. 1151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushStackHandler(); 1152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If an exception not caught by another handler occurs, this handler 1153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // returns control to the code after the b(&invoke) above, which 1154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // restores all kCalleeSaved registers (including cp and fp) to their 1155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // saved values before returning a failure to C. 1156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Invoke the function by calling through JS entry trampoline builtin. 1158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Notice that we cannot store a reference to the trampoline code directly in 1159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // this stub, because runtime stubs are not traversed when doing GC. 1160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Expected registers by Builtins::JSEntryTrampoline 1162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: code entry 1163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: function 1164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: receiver 1165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: argc 1166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r7: argv 1167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (type() == StackFrame::ENTRY_CONSTRUCT) { 1168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline, 1169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate()); 1170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(construct_entry)); 1171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference entry(Builtins::kJSEntryTrampoline, isolate()); 1173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(entry)); 1174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(ip, MemOperand(ip)); // deref address 1176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Branch and link to JSEntryTrampoline. 1178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the address points to the start of the code object, skip the header 1179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); 1180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtctr(ip); 1181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bctrl(); // make the call 1182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Unlink this frame from the handler chain. 1184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopStackHandler(); 1185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&exit); // r3 holds result 1187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if the current stack frame is marked as the outermost JS frame. 1188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label non_outermost_js_2; 1189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(r8); 119062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmpi(r8, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME)); 1191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&non_outermost_js_2); 1192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r9, Operand::Zero()); 1193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r8, Operand(ExternalReference(js_entry_sp))); 1194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r9, MemOperand(r8)); 1195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&non_outermost_js_2); 1196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore the top frame descriptors from the stack. 1198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(r6); 1199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 1200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r6, MemOperand(ip)); 1201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Reset the stack to the callee saved registers. 1203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 1204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restore callee-saved double registers. 1206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ MultiPopDoubles(kCalleeSavedDoubles); 1207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restore callee-saved registers. 1209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPop(kCalleeSaved); 1210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Return 1212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize)); 1213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mtlr(r0); 1214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blr(); 1215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1217109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid RegExpExecStub::Generate(MacroAssembler* masm) { 1218109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Just jump directly to runtime if native RegExp is not selected at compile 1219109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// time or if regexp entry in generated code is turned off runtime switch or 1220109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// at compilation. 1221109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#ifdef V8_INTERPRETED_REGEXP 1222109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallRuntime(Runtime::kRegExpExec); 1223109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else // V8_INTERPRETED_REGEXP 1224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1225109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Stack frame on entry. 1226109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // sp[0]: last_match_info (expected JSArray) 1227109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // sp[4]: previous index 1228109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // sp[8]: subject string 1229109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // sp[12]: JSRegExp object 1230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1231109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kLastMatchInfoOffset = 0 * kPointerSize; 1232109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kPreviousIndexOffset = 1 * kPointerSize; 1233109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kSubjectOffset = 2 * kPointerSize; 1234109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kJSRegExpOffset = 3 * kPointerSize; 1235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1236109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label runtime, br_over, encoding_type_UC16; 1237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1238109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Allocation of registers for this function. These are in callee save 1239109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // registers and will be preserved by the call to the native RegExp code, as 1240109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // this code is called using the normal C calling convention. When calling 1241109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // directly from generated code the native RegExp code will not do a GC and 1242109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // therefore the content of these registers are safe to use after the call. 1243109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register subject = r14; 1244109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register regexp_data = r15; 1245109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register last_match_info_elements = r16; 1246109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register code = r17; 1247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1248109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Ensure register assigments are consistent with callee save masks 1249109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(subject.bit() & kCalleeSaved); 1250109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(regexp_data.bit() & kCalleeSaved); 1251109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(last_match_info_elements.bit() & kCalleeSaved); 1252109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(code.bit() & kCalleeSaved); 1253f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1254109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Ensure that a RegExp stack is allocated. 1255109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference address_of_regexp_stack_memory_address = 1256109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference::address_of_regexp_stack_memory_address(isolate()); 1257109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference address_of_regexp_stack_memory_size = 1258109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference::address_of_regexp_stack_memory_size(isolate()); 1259109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(r3, Operand(address_of_regexp_stack_memory_size)); 1260109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, MemOperand(r3, 0)); 1261109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r3, Operand::Zero()); 1262109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&runtime); 1263f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1264109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check that the first argument is a JSRegExp object. 1265109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, MemOperand(sp, kJSRegExpOffset)); 1266109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(r3, &runtime); 1267109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareObjectType(r3, r4, r4, JS_REGEXP_TYPE); 1268109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&runtime); 1269f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1270109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check that the RegExp has been compiled (data contains a fixed array). 1271109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(regexp_data, FieldMemOperand(r3, JSRegExp::kDataOffset)); 1272109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 1273109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TestIfSmi(regexp_data, r0); 1274109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected, cr0); 1275109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareObjectType(regexp_data, r3, r3, FIXED_ARRAY_TYPE); 1276109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected); 1277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1279109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // regexp_data: RegExp data (FixedArray) 1280109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 1281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); 1282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // DCHECK(Smi::FromInt(JSRegExp::IRREGEXP) < (char *)0xffffu); 1283109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpSmiLiteral(r3, Smi::FromInt(JSRegExp::IRREGEXP), r0); 1284109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&runtime); 1285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1286109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // regexp_data: RegExp data (FixedArray) 1287109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check that the number of captures fit in the static offsets vector buffer. 1288109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r5, 1289109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 1290109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check (number_of_captures + 1) * 2 <= offsets vector size 1291109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Or number_of_captures * 2 <= offsets vector size - 2 1292109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // SmiToShortArrayOffset accomplishes the multiplication by 2 and 1293109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // SmiUntag (which is a nop for 32-bit). 1294109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToShortArrayOffset(r5, r5); 1295109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); 1296109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpli(r5, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2)); 1297109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bgt(&runtime); 1298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1299109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reset offset for possibly sliced string. 1300109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ li(r11, Operand::Zero()); 1301109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(subject, MemOperand(sp, kSubjectOffset)); 1302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(subject, &runtime); 1303109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r6, subject); // Make a copy of the original subject string. 1304109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // subject: subject string 1305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r6: subject string 1306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // regexp_data: RegExp data (FixedArray) 1307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Handle subject string according to its encoding and representation: 1308109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (1) Sequential string? If yes, go to (4). 1309109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (2) Sequential or cons? If not, go to (5). 1310109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (3) Cons string. If the string is flat, replace subject with first string 1311109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // and go to (1). Otherwise bail out to runtime. 1312109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (4) Sequential string. Load regexp code according to encoding. 1313109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (E) Carry on. 1314109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch /// [...] 1315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Deferred code at the end of the stub: 1317109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (5) Long external string? If not, go to (7). 1318109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (6) External string. Make it, offset-wise, look like a sequential string. 1319109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Go to (4). 1320109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (7) Short external string or not a string? If yes, bail out to runtime. 132162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // (8) Sliced or thin string. Replace subject with parent. Go to (1). 1322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1323109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */, 1324109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch not_seq_nor_cons /* 5 */, not_long_external /* 7 */; 1325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1326109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&check_underlying); 1327109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset)); 1328109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset)); 1329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (1) Sequential string? If yes, go to (4). 1331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1332109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT((kIsNotStringMask | kStringRepresentationMask | 133362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch kShortExternalStringMask) == 0xa7); 1334109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andi(r4, r3, Operand(kIsNotStringMask | kStringRepresentationMask | 1335109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kShortExternalStringMask)); 1336109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); 1337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&seq_string, cr0); // Go to (4). 1338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1339109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (2) Sequential or cons? If not, go to (5). 1340109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kConsStringTag < kExternalStringTag); 1341109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 134262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(kThinStringTag > kExternalStringTag); 1343109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 1344109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 1345109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kExternalStringTag < 0xffffu); 1346109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r4, Operand(kExternalStringTag)); 1347109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bge(¬_seq_nor_cons); // Go to (5). 1348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1349109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (3) Cons string. Check that it's flat. 1350109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Replace subject with first string and reload instance type. 1351109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, FieldMemOperand(subject, ConsString::kSecondOffset)); 1352109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(r3, Heap::kempty_stringRootIndex); 1353109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&runtime); 1354109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); 1355109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&check_underlying); 1356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1357109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (4) Sequential string. Load regexp code according to encoding. 1358f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&seq_string); 1359f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // subject: sequential subject string (or look-alike, external string) 1360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: original subject string 1361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load previous index and check range before r6 is overwritten. We have to 1362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // use r6 instead of subject here because subject might have been only made 1363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // to look like a sequential string when it actually is an external string. 1364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r4, MemOperand(sp, kPreviousIndexOffset)); 1365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r4, &runtime); 1366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r6, FieldMemOperand(r6, String::kLengthOffset)); 1367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpl(r6, r4); 1368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ble(&runtime); 1369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r4); 1370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 137162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(8 == kOneByteStringTag); 1372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kTwoByteStringTag == 0); 137362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(kStringEncodingMask == 8); 1374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ExtractBitMask(r6, r3, kStringEncodingMask, SetRC); 1375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&encoding_type_UC16, cr0); 1376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(code, 1377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset)); 1378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&br_over); 1379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&encoding_type_UC16); 1380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(code, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); 1381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&br_over); 1382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (E) Carry on. String handling is done. 1384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // code: irregexp code 1385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the irregexp code has been generated for the actual string 1386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // encoding. If it has, the field contains a code object otherwise it contains 1387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // a smi (code flushing support). 1388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(code, &runtime); 1389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: previous index 1391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: encoding of subject string (1 if one_byte, 0 if two_byte); 1392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // code: Address of generated regexp code 1393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // subject: Subject string 1394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // regexp_data: RegExp data (FixedArray) 1395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // All checks done. Now push arguments for native regexp code. 1396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 1, r3, r5); 1397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Isolates: note we add an additional parameter here (isolate pointer). 1399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int kRegExpExecuteArguments = 10; 1400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int kParameterRegisters = 8; 1401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); 1402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stack pointer now points to cell where return address is to be written. 1404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Arguments are before that on the stack or in registers. 1405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 10 (in stack parameter area): Pass current isolate address. 1407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(ExternalReference::isolate_address(isolate()))); 1408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r3, MemOperand(sp, (kStackFrameExtraParamSlot + 1) * kPointerSize)); 1409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 9 is a dummy that reserves the space used for 1411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the return address added by the ExitFrame in native calls. 1412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 8 (r10): Indicate that this is a direct call from JavaScript. 1414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r10, Operand(1)); 1415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 7 (r9): Start (high end) of backtracking stack memory area. 1417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(address_of_regexp_stack_memory_address)); 1418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, MemOperand(r3, 0)); 1419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r5, Operand(address_of_regexp_stack_memory_size)); 1420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r5, MemOperand(r5, 0)); 1421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(r9, r3, r5); 1422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 6 (r8): Set the number of capture registers to zero to force 1424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // global egexps to behave as non-global. This does not affect non-global 1425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // regexps. 1426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r8, Operand::Zero()); 1427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 5 (r7): static offsets vector buffer. 1429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov( 1430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r7, 1431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(ExternalReference::address_of_static_offsets_vector(isolate()))); 1432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For arguments 4 (r6) and 3 (r5) get string length, calculate start of data 1434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // and calculate the shift of the index (0 for one-byte and 1 for two-byte). 1435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r18, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); 1436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ xori(r6, r6, Operand(1)); 1437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the length from the original subject string from the previous stack 1438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // frame. Therefore we have to use fp, which points exactly to two pointer 1439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // sizes below the previous sp. (Because creating a new stack frame pushes 1440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) 1441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); 1442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If slice offset is not 0, load the length from the original sliced string. 1443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 4, r6: End of string data 1444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 3, r5: Start of string data 1445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Prepare start and end index of the input. 1446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeft_(r11, r11, r6); 1447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(r11, r18, r11); 1448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeft_(r5, r4, r6); 1449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(r5, r11, r5); 1450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r18, FieldMemOperand(subject, String::kLengthOffset)); 1452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r18); 1453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeft_(r6, r18, r6); 1454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(r6, r11, r6); 1455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 2 (r4): Previous index. 1457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Already there 1458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 1 (r3): Subject string. 1460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r3, subject); 1461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Locate the code entry and call it. 1463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(code, code, Operand(Code::kHeaderSize - kHeapObjectTag)); 1464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DirectCEntryStub stub(isolate()); 1466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub.GenerateCall(masm, code); 1467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LeaveExitFrame(false, no_reg, true); 1469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r3: result (int32) 1471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // subject: subject string (callee saved) 1472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // regexp_data: RegExp data (callee saved) 1473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // last_match_info_elements: Last match info elements (callee saved) 1474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check the result. 1475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label success; 1476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpwi(r3, Operand(1)); 1477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We expect exactly one result since we force the called regexp to behave 1478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // as non-global. 1479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&success); 1480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label failure; 1481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpwi(r3, Operand(NativeRegExpMacroAssembler::FAILURE)); 1482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&failure); 1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpwi(r3, Operand(NativeRegExpMacroAssembler::EXCEPTION)); 1484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If not exception it can only be retry. Handle that in the runtime system. 1485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&runtime); 1486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Result must now be exception. If there is no pending exception already a 1487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stack overflow (on the backtrack stack) was detected in RegExp code but 1488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // haven't created the exception yet. Handle that in the runtime system. 1489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // TODO(592): Rerunning the RegExp to get the stack overflow exception. 1490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r4, Operand(isolate()->factory()->the_hole_value())); 1491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r5, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate()))); 1493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, MemOperand(r5, 0)); 1494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r3, r4); 1495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&runtime); 1496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // For exception, throw the exception again. 1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kRegExpExecReThrow); 1499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&failure); 1501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For failure and exception return null. 1502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(isolate()->factory()->null_value())); 1503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(sp, sp, Operand(4 * kPointerSize)); 1504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 1505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Process the result from the native regexp code. 1507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&success); 1508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r4, 1509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 1510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Calculate number of capture registers (number_of_captures + 1) * 2. 1511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // SmiToShortArrayOffset accomplishes the multiplication by 2 and 1512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // SmiUntag (which is a nop for 32-bit). 1513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToShortArrayOffset(r4, r4); 1514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r4, r4, Operand(2)); 1515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1516c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check that the last match info is a FixedArray. 1517c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ LoadP(last_match_info_elements, MemOperand(sp, kLastMatchInfoOffset)); 1518c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ JumpIfSmi(last_match_info_elements, &runtime); 1519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check that the object has fast elements. 1520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, 1521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); 1522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareRoot(r3, Heap::kFixedArrayMapRootIndex); 1523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&runtime); 1524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the last match info has space for the capture registers and the 1525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // additional information. 1526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP( 1527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r3, FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); 1528c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ addi(r5, r4, Operand(RegExpMatchInfo::kLastMatchOverhead)); 1529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r0, r3); 1530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r5, r0); 1531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bgt(&runtime); 1532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: number of capture registers 1534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // subject: subject string 1535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Store the capture count. 1536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiTag(r5, r4); 1537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r5, FieldMemOperand(last_match_info_elements, 1538c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch RegExpMatchInfo::kNumberOfCapturesOffset), 1539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r0); 1540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Store last subject and last input. 1541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(subject, FieldMemOperand(last_match_info_elements, 1542c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch RegExpMatchInfo::kLastSubjectOffset), 1543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r0); 1544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r5, subject); 1545c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ RecordWriteField(last_match_info_elements, 1546c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch RegExpMatchInfo::kLastSubjectOffset, subject, r10, 1547c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kLRHasNotBeenSaved, kDontSaveFPRegs); 1548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(subject, r5); 1549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(subject, FieldMemOperand(last_match_info_elements, 1550c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch RegExpMatchInfo::kLastInputOffset), 1551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r0); 1552c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ RecordWriteField(last_match_info_elements, 1553c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch RegExpMatchInfo::kLastInputOffset, subject, r10, 1554c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kLRHasNotBeenSaved, kDontSaveFPRegs); 1555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get the static offsets vector filled by the native regexp code. 1557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference address_of_static_offsets_vector = 1558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::address_of_static_offsets_vector(isolate()); 1559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r5, Operand(address_of_static_offsets_vector)); 1560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: number of capture registers 1562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: offsets vector 1563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label next_capture; 1564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Capture register counter starts from number of capture registers and 1565c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // counts down until wrapping after zero. 1566c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ addi(r3, last_match_info_elements, 1567c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Operand(RegExpMatchInfo::kFirstCaptureOffset - kHeapObjectTag - 1568c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kPointerSize)); 1569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r5, r5, Operand(-kIntSize)); // bias down for lwzu 1570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtctr(r4); 1571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&next_capture); 1572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Read the value from the static offsets vector buffer. 1573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwzu(r6, MemOperand(r5, kIntSize)); 1574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Store the smi value in the last match info. 1575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiTag(r6); 1576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StorePU(r6, MemOperand(r3, kPointerSize)); 1577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bdnz(&next_capture); 1578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return last match info. 1580c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mr(r3, last_match_info_elements); 1581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(sp, sp, Operand(4 * kPointerSize)); 1582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 1583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Do the runtime call to execute the regexp. 1585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&runtime); 1586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kRegExpExec); 1587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Deferred code for string handling. 1589109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (5) Long external string? If not, go to (7). 1590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_seq_nor_cons); 1591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare flags are still set. 1592109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bgt(¬_long_external); // Go to (7). 1593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1594109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (6) External string. Make it, offset-wise, look like a sequential string. 1595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&external_string); 1596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset)); 1597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset)); 1598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (FLAG_debug_code) { 1599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Assert that we do not have a cons or slice (indirect strings) here. 1600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Sequential strings have already been ruled out. 1601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kIsIndirectStringMask == 1); 1602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r3, Operand(kIsIndirectStringMask)); 1603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Assert(eq, kExternalStringExpectedButNotFound, cr0); 1604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(subject, 1606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(subject, ExternalString::kResourceDataOffset)); 1607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Move the pointer so that offset-wise, it looks like a sequential string. 1608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 1609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subi(subject, subject, 1610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 1611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&seq_string); // Go to (4). 1612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1613109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (7) Short external string or not a string? If yes, bail out to runtime. 1614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_long_external); 1615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag != 0); 1616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r4, Operand(kIsNotStringMask | kShortExternalStringMask)); 1617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&runtime, cr0); 1618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 161962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // (8) Sliced or thin string. Replace subject with parent. Go to (4). 162062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label thin_string; 162162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmpi(r4, Operand(kThinStringTag)); 162262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ beq(&thin_string); 1623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load offset into r11 and replace subject string with parent. 1624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset)); 1625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r11); 1626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); 1627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&check_underlying); // Go to (4). 162862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 162962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ bind(&thin_string); 163062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadP(subject, FieldMemOperand(subject, ThinString::kActualOffset)); 163162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ b(&check_underlying); // Go to (4). 1632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif // V8_INTERPRETED_REGEXP 1633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { 1637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r3 : number of arguments to the construct function 1638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r4 : the function to call 1639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r5 : feedback vector 1640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r6 : slot in feedback vector (Smi) 1641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 1642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Number-of-arguments register must be smi-tagged to call out. 1644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiTag(r3); 1645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(r6, r5, r4, r3); 1646f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(cp); 1647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallStub(stub); 1649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1650f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Pop(cp); 1651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(r6, r5, r4, r3); 1652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(r3); 1653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void GenerateRecordCallTarget(MacroAssembler* masm) { 1657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Cache the called function in a feedback vector slot. Cache states 1658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // are uninitialized, monomorphic (indicated by a JSFunction), and 1659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // megamorphic. 1660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3 : number of arguments to the construct function 1661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4 : the function to call 1662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r5 : feedback vector 1663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6 : slot in feedback vector (Smi) 1664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label initialize, done, miss, megamorphic, not_array_function; 1665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 166662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(*FeedbackVector::MegamorphicSentinel(masm->isolate()), 1667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm->isolate()->heap()->megamorphic_symbol()); 166862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(*FeedbackVector::UninitializedSentinel(masm->isolate()), 1669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm->isolate()->heap()->uninitialized_symbol()); 1670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 167113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch const int count_offset = FixedArray::kHeaderSize + kPointerSize; 167213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the cache state into r8. 1674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiToPtrArrayOffset(r8, r6); 1675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(r8, r5, r8); 1676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r8, FieldMemOperand(r8, FixedArray::kHeaderSize)); 1677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // A monomorphic cache hit or an already megamorphic state: invoke the 1679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // function without changing the state. 1680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We don't know if r8 is a WeakCell or a Symbol, but it's harmless to read at 168162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // this position in a symbol (see static asserts in feedback-vector.h). 1682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label check_allocation_site; 1683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register feedback_map = r9; 1684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register weak_value = r10; 1685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(weak_value, FieldMemOperand(r8, WeakCell::kValueOffset)); 1686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, weak_value); 1687f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ beq(&done); 1688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r8, Heap::kmegamorphic_symbolRootIndex); 1689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&done); 1690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(feedback_map, FieldMemOperand(r8, HeapObject::kMapOffset)); 1691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex); 1692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&check_allocation_site); 1693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the weak cell is cleared, we have a new chance to become monomorphic. 1695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(weak_value, &initialize); 1696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&megamorphic); 1697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&check_allocation_site); 1699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If we came here, we need to see if we are the array function. 1700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If we didn't have a matching function, and we didn't find the megamorph 1701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // sentinel, then we have in the slot either some other function or an 1702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // AllocationSite. 1703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(feedback_map, Heap::kAllocationSiteMapRootIndex); 1704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&miss); 1705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make sure the function is the Array() function 1707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8); 1708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, r8); 1709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&megamorphic); 1710f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ b(&done); 1711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 1713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // A monomorphic miss (i.e, here the cache is not uninitialized) goes 1715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // megamorphic. 1716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r8, Heap::kuninitialized_symbolRootIndex); 1717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&initialize); 1718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // MegamorphicSentinel is an immortal immovable object (undefined) so no 1719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // write-barrier is needed. 1720958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&megamorphic); 1721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiToPtrArrayOffset(r8, r6); 1722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(r8, r5, r8); 1723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); 1724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(ip, FieldMemOperand(r8, FixedArray::kHeaderSize), r0); 1725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ jmp(&done); 1726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // An uninitialized cache is patched with the function 1728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&initialize); 1729958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make sure the function is the Array() function. 1731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8); 1732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, r8); 1733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(¬_array_function); 1734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The target function is the Array constructor, 1736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Create an AllocationSite if we don't already have it, store it in the 1737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // slot. 1738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CreateAllocationSiteStub create_stub(masm->isolate()); 1739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallStubInRecordCallTarget(masm, &create_stub); 1740f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ b(&done); 1741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(¬_array_function); 1743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CreateWeakCellStub weak_cell_stub(masm->isolate()); 1745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallStubInRecordCallTarget(masm, &weak_cell_stub); 174613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1747f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&done); 174813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1749f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Increment the call count for all function calls. 175013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ SmiToPtrArrayOffset(r8, r6); 175113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ add(r8, r5, r8); 175213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 175313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ LoadP(r7, FieldMemOperand(r8, count_offset)); 175413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0); 175513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ StoreP(r7, FieldMemOperand(r8, count_offset), r0); 1756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CallConstructStub::Generate(MacroAssembler* masm) { 1760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r3 : number of arguments 1761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r4 : the function to call 1762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r5 : feedback vector 1763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r6 : slot in feedback vector (Smi, for RecordCallTarget) 1764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label non_function; 1766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check that the function is not a smi. 1767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(r4, &non_function); 1768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check that the function is a JSFunction. 1769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r4, r8, r8, JS_FUNCTION_TYPE); 1770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&non_function); 1771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateRecordCallTarget(masm); 1773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiToPtrArrayOffset(r8, r6); 1775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(r8, r5, r8); 1776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Put the AllocationSite from the feedback vector into r5, or undefined. 1777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize)); 1778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r8, FieldMemOperand(r5, AllocationSite::kMapOffset)); 1779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex); 1780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 1781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); 1782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, r5, r5, r8); 1783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label feedback_register_initialized; 1785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&feedback_register_initialized); 1786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); 1787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&feedback_register_initialized); 1788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertUndefinedOrAllocationSite(r5, r8); 1791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Pass function as new target. 1793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r6, r4); 1794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Tail call to the function-specific construct stub (still in the caller 1796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // context at this point). 1797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 1798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r7, FieldMemOperand(r7, SharedFunctionInfo::kConstructStubOffset)); 1799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addi(ip, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); 1800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpToJSEntry(ip); 1801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&non_function); 1803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r6, r4); 1804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 1805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// StringCharCodeAtGenerator 1809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 1810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If the receiver is a smi trigger the non-string case. 1811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (check_mode_ == RECEIVER_IS_UNKNOWN) { 1812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(object_, receiver_not_string_); 1813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Fetch the instance type of the receiver into result register. 1815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 1816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 1817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If the receiver is not a string trigger the non-string case. 1818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, result_, Operand(kIsNotStringMask)); 1819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(receiver_not_string_, cr0); 1820958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If the index is non-smi trigger the non-smi case. 1823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(index_, &index_not_smi_); 1824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&got_smi_index_); 1825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for index out of range. 1827958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(ip, FieldMemOperand(object_, String::kLengthOffset)); 1828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpl(ip, index_); 1829958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ble(index_out_of_range_); 1830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(index_); 1832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringCharLoadGenerator::Generate(masm, object_, index_, result_, 1834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &call_runtime_); 1835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiTag(result_); 1837958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&exit_); 1838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1839958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1840958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringCharCodeAtGenerator::GenerateSlow( 1842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm, EmbedMode embed_mode, 1843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const RuntimeCallHelper& call_helper) { 1844958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase); 1845958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1846958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Index is not a smi. 1847958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&index_not_smi_); 1848958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If index is a heap number, try converting it to an integer. 1849958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckMap(index_, result_, Heap::kHeapNumberMapRootIndex, index_not_number_, 1850958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DONT_DO_SMI_CHECK); 1851958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_helper.BeforeCall(masm); 1852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (embed_mode == PART_OF_IC_HANDLER) { 1853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(LoadWithVectorDescriptor::VectorRegister(), 1854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadWithVectorDescriptor::SlotRegister(), object_, index_); 1855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // index_ is consumed by runtime conversion function. 1857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(object_, index_); 1858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 185913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ CallRuntime(Runtime::kNumberToSmi); 1860958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Save the conversion result before the pop instructions below 1861958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // have a chance to overwrite it. 1862958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(index_, r3); 1863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (embed_mode == PART_OF_IC_HANDLER) { 1864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(LoadWithVectorDescriptor::VectorRegister(), 1865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadWithVectorDescriptor::SlotRegister(), object_); 1866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(object_); 1868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1869958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Reload the instance type. 1870958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 1871958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 1872958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_helper.AfterCall(masm); 1873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If index is still not a smi, it must be out of range. 1874958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(index_, index_out_of_range_); 1875958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Otherwise, return to the fast path. 1876958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&got_smi_index_); 1877958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1878958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call runtime. We get here when the receiver is a string and the 1879958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // index is a number, but the code of getting the actual character 1880958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // is too complex (e.g., when the string needs to be flattened). 1881958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&call_runtime_); 1882958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_helper.BeforeCall(masm); 1883958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiTag(index_); 1884958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(object_, index_); 1885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kStringCharCodeAtRT); 1886958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(result_, r3); 1887958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_helper.AfterCall(masm); 1888958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&exit_); 1889958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1890958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); 1891958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1892958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1893958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, 1894958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register left, 1895958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register right, 1896958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch1, 1897958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch2) { 1898958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register length = scratch1; 1899958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1900958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare lengths. 1901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label strings_not_equal, check_zero_length; 1902958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(length, FieldMemOperand(left, String::kLengthOffset)); 1903958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset)); 1904958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(length, scratch2); 1905958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&check_zero_length); 1906958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&strings_not_equal); 1907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(NOT_EQUAL)); 1908958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 1909958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1910958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if the length is zero. 1911958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label compare_chars; 1912958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&check_zero_length); 1913958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 1914958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(length, Operand::Zero()); 1915958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&compare_chars); 1916958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 1917958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 1918958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1919958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare characters. 1920958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&compare_chars); 1921958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, 1922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &strings_not_equal); 1923958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1924958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Characters are equal. 1925958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 1926958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 1927958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1928958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1929958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1930958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringHelper::GenerateCompareFlatOneByteStrings( 1931958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Register left, Register right, Register scratch1, 1932958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch2, Register scratch3) { 1933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label result_not_equal, compare_lengths; 1934958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Find minimum length and length difference. 1935958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch1, FieldMemOperand(left, String::kLengthOffset)); 1936958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset)); 1937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ sub(scratch3, scratch1, scratch2, LeaveOE, SetRC); 1938958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register length_delta = scratch3; 1939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 1940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(gt, scratch1, scratch2, scratch1, cr0); 1941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label skip; 1943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ble(&skip, cr0); 1944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(scratch1, scratch2); 1945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&skip); 1946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1947958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register min_length = scratch1; 1948958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 1949958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(min_length, Operand::Zero()); 1950958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&compare_lengths); 1951958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1952958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare loop. 1953958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2, 1954958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &result_not_equal); 1955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare lengths - strings up to min-length are equal. 1957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&compare_lengths); 1958958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); 1959958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Use length_delta as result if it's zero. 1960958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r3, length_delta); 1961958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r3, Operand::Zero()); 1962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&result_not_equal); 1963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Conditionally update the result based either on length_delta or 1964958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the last comparion performed in the loop above. 1965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 1966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r4, Smi::FromInt(GREATER)); 1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r5, Smi::FromInt(LESS)); 1968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, r3, r0, r4); 1969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(lt, r3, r5, r3); 1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 1971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label less_equal, equal; 1973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ble(&less_equal); 1974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r3, Smi::FromInt(GREATER)); 1975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 1976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&less_equal); 1977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&equal); 1978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r3, Smi::FromInt(LESS)); 1979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&equal); 1980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 1981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1982958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1983958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1984958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1985958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringHelper::GenerateOneByteCharsCompareLoop( 1986958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Register left, Register right, Register length, 1987958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch1, Label* chars_not_equal) { 1988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Change index to run from -length to -1 by adding length to string 1989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // start. This means that loop ends when index reaches zero, which 1990958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // doesn't need an additional compare. 1991958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(length); 1992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(scratch1, length, 1993958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 1994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(left, left, scratch1); 1995958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(right, right, scratch1); 1996958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subfic(length, length, Operand::Zero()); 1997958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register index = length; // index = -length; 1998958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare loop. 2000958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label loop; 2001958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&loop); 2002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbzx(scratch1, MemOperand(left, index)); 2003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbzx(r0, MemOperand(right, index)); 2004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(scratch1, r0); 2005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(chars_not_equal); 2006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(index, index, Operand(1)); 2007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(index, Operand::Zero()); 2008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&loop); 2009958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2010958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2011958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2012958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { 2013958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------- S t a t e ------------- 2014958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r4 : left 2015958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r3 : right 2016958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- lr : return address 2017958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------------------------------- 2018958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2019958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load r5 with the allocation site. We stick an undefined dummy value here 2020958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // and replace it with the real allocation site later when we instantiate this 2021958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate(). 202213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Move(r5, isolate()->factory()->undefined_value()); 2023958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2024958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure that we actually patched the allocation site. 2025958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (FLAG_debug_code) { 2026958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TestIfSmi(r5, r0); 2027958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Assert(ne, kExpectedAllocationSite, cr0); 2028958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r5); 2029958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r5, FieldMemOperand(r5, HeapObject::kMapOffset)); 2030958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(ip, Heap::kAllocationSiteMapRootIndex); 2031958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r5, ip); 2032958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(r5); 2033958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Assert(eq, kExpectedAllocationSite); 2034958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2035958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2036958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Tail call into the stub that handles binary operations with allocation 2037958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // sites. 2038958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier BinaryOpWithAllocationSiteStub stub(isolate(), state()); 2039958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallStub(&stub); 2040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2041958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2042958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CompareICStub::GenerateBooleans(MacroAssembler* masm) { 2044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(CompareICState::BOOLEAN, state()); 2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label miss; 2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CheckMap(r4, r5, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); 2048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CheckMap(r3, r6, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); 2049109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!Token::IsEqualityOp(op())) { 2050109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r4, FieldMemOperand(r4, Oddball::kToNumberOffset)); 2051109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertSmi(r4); 2052109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset)); 2053109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertSmi(r3); 2054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2055109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ sub(r3, r4, r3); 2056109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 2057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&miss); 2059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateMiss(masm); 2060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2063958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateSmis(MacroAssembler* masm) { 2064958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(state() == CompareICState::SMI); 2065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 2066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(r5, r4, r3); 2067958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r5, &miss); 2068958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (GetCondition() == eq) { 2070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For equality we do not care about the sign of the result. 2071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // __ sub(r3, r3, r4, SetCC); 2072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ sub(r3, r3, r4); 2073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Untag before subtracting to avoid handling overflow. 2075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r4); 2076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r3); 2077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ sub(r3, r4, r3); 2078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2080958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2081958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 2082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 2083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2086958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateNumbers(MacroAssembler* masm) { 2087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(state() == CompareICState::NUMBER); 2088958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label generic_stub; 2090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label unordered, maybe_undefined1, maybe_undefined2; 2091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 2092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label equal, less_than; 2093958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (left() == CompareICState::SMI) { 2095958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r4, &miss); 2096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2097958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (right() == CompareICState::SMI) { 2098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r3, &miss); 2099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Inlining the double comparison and falling back to the general compare 2102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stub if NaN is involved. 2103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load left and right operand. 2104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label done, left, left_smi, right_smi; 2105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r3, &right_smi); 2106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckMap(r3, r5, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, 2107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DONT_DO_SMI_CHECK); 2108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d1, FieldMemOperand(r3, HeapNumber::kValueOffset)); 2109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&left); 2110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&right_smi); 2111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToDouble(d1, r3); 2112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&left); 2114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r4, &left_smi); 2115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckMap(r4, r5, Heap::kHeapNumberMapRootIndex, &maybe_undefined2, 2116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DONT_DO_SMI_CHECK); 2117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d0, FieldMemOperand(r4, HeapNumber::kValueOffset)); 2118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&done); 2119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&left_smi); 2120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToDouble(d0, r4); 2121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&done); 2123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare operands 2125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fcmpu(d0, d1); 2126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Don't base result on status bits when a NaN is involved. 2128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bunordered(&unordered); 2129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return a result of -1, 0, or 1, based on status bits. 2131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 2132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(EQUAL == 0); 2133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r4, Operand(GREATER)); 2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r5, Operand(LESS)); 2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, r3, r0, r4); 2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(lt, r3, r5, r3); 2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&equal); 2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blt(&less_than); 2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // assume greater than 2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(GREATER)); 2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&equal); 2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(EQUAL)); 2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&less_than); 2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(LESS)); 2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&unordered); 2153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&generic_stub); 2154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CompareICStub stub(isolate(), op(), CompareICState::GENERIC, 2155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompareICState::GENERIC, CompareICState::GENERIC); 2156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 2157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&maybe_undefined1); 2159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (Token::IsOrderedRelationalCompareOp(op())) { 2160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); 2161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss); 2162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r4, &unordered); 2163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(r4, r5, r5, HEAP_NUMBER_TYPE); 2164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&maybe_undefined2); 2165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&unordered); 2166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&maybe_undefined2); 2169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (Token::IsOrderedRelationalCompareOp(op())) { 2170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareRoot(r4, Heap::kUndefinedValueRootIndex); 2171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&unordered); 2172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 2175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 2176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { 2180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(state() == CompareICState::INTERNALIZED_STRING); 2181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss, not_equal; 2182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Registers containing left and right operands respectively. 2184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register left = r4; 2185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register right = r3; 2186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp1 = r5; 2187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp2 = r6; 2188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are heap objects. 2190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfEitherSmi(left, right, &miss); 2191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are symbols. 2193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 2194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 2195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 2196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 2197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 2198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(tmp1, tmp1, tmp2); 2199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 2200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss, cr0); 2201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Internalized strings are compared by identity. 2203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(left, right); 2204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(¬_equal); 2205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure r3 is non-zero. At this point input operands are 2206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // guaranteed to be non-zero. 2207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(right.is(r3)); 2208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(EQUAL == 0); 2209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 2210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 2211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_equal); 2212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 2215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 2216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { 2220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(state() == CompareICState::UNIQUE_NAME); 2221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(GetCondition() == eq); 2222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 2223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Registers containing left and right operands respectively. 2225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register left = r4; 2226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register right = r3; 2227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp1 = r5; 2228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp2 = r6; 2229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are heap objects. 2231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfEitherSmi(left, right, &miss); 2232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are unique names. This leaves the instance 2234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // types loaded in tmp1 and tmp2. 2235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 2236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 2237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 2238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 2239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotUniqueNameInstanceType(tmp1, &miss); 2241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotUniqueNameInstanceType(tmp2, &miss); 2242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Unique names are compared by identity. 2244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(left, right); 2245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss); 2246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure r3 is non-zero. At this point input operands are 2247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // guaranteed to be non-zero. 2248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(right.is(r3)); 2249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(EQUAL == 0); 2250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 2251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 2252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 2255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 2256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateStrings(MacroAssembler* masm) { 2260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(state() == CompareICState::STRING); 2261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss, not_identical, is_symbol; 2262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool equality = Token::IsEqualityOp(op()); 2264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Registers containing left and right operands respectively. 2266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register left = r4; 2267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register right = r3; 2268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp1 = r5; 2269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp2 = r6; 2270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp3 = r7; 2271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp4 = r8; 2272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are heap objects. 2274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfEitherSmi(left, right, &miss); 2275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are strings. This leaves the instance 2277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // types loaded in tmp1 and tmp2. 2278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 2279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 2280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 2281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 2282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kNotStringTag != 0); 2283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(tmp3, tmp1, tmp2); 2284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, tmp3, Operand(kIsNotStringMask)); 2285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss, cr0); 2286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Fast check for identical strings. 2288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(left, right); 2289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(EQUAL == 0); 2290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 2291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(¬_identical); 2292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 2293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_identical); 2295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Handle not identical strings. 2297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both strings are internalized strings. If they are, we're done 2299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // because we already know they are not identical. We know they are both 2300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // strings. 2301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (equality) { 2302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(GetCondition() == eq); 2303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kInternalizedTag == 0); 2304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(tmp3, tmp1, tmp2); 2305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, tmp3, Operand(kIsNotInternalizedMask)); 2306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure r3 is non-zero. At this point input operands are 2307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // guaranteed to be non-zero. 2308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(right.is(r3)); 2309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(eq, cr0); 2310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both strings are sequential one-byte. 2313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label runtime; 2314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4, 2315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &runtime); 2316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare flat one-byte strings. Returns when done. 2318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (equality) { 2319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, 2320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier tmp2); 2321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1, 2323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier tmp2, tmp3); 2324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Handle more complex cases in runtime. 2327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&runtime); 2328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (equality) { 23293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 23303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 23313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Push(left, right); 23323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CallRuntime(Runtime::kStringEqual); 23333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 23343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadRoot(r4, Heap::kTrueValueRootIndex); 23353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ sub(r3, r3, r4); 23363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Ret(); 2337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 23383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Push(left, right); 2339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kStringCompare); 2340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 2343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 2344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CompareICStub::GenerateReceivers(MacroAssembler* masm) { 2348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(CompareICState::RECEIVER, state()); 2349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 2350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(r5, r4, r3); 2351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r5, &miss); 2352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 2354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r3, r5, r5, FIRST_JS_RECEIVER_TYPE); 2355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blt(&miss); 2356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r4, r5, r5, FIRST_JS_RECEIVER_TYPE); 2357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blt(&miss); 2358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(GetCondition() == eq); 2360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ sub(r3, r3, r4); 2361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 2364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 2365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CompareICStub::GenerateKnownReceivers(MacroAssembler* masm) { 2369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 2370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<WeakCell> cell = Map::WeakCellForMap(known_map_); 2371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(r5, r4, r3); 2372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r5, &miss); 2373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ GetWeakValue(r7, cell); 2374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset)); 2375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset)); 2376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r5, r7); 2377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss); 2378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r6, r7); 2379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss); 2380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (Token::IsEqualityOp(op())) { 2382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(r3, r3, r4); 2383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (op() == Token::LT || op() == Token::LTE) { 2386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r5, Smi::FromInt(GREATER)); 2387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r5, Smi::FromInt(LESS)); 2389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(r4, r3, r5); 2391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kCompare); 2392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 2395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 2396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateMiss(MacroAssembler* masm) { 2400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 2401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call the runtime system in a fresh internal frame. 2402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 2403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(r4, r3); 2404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(r4, r3); 2405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r0, Smi::FromInt(op())); 2406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 2407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCompareIC_Miss); 2408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compute the entry point of the rewritten stub. 2409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r5, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); 2410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore registers. 2411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Pop(r4, r3); 2412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpToJSEntry(r5); 2415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// This stub is paired with DirectCEntryStub::GenerateCall 2419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid DirectCEntryStub::Generate(MacroAssembler* masm) { 2420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Place the return address on the stack, making the call 2421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // GC safe. The RegExp backend also relies on this. 2422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 2423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); 2424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Call(ip); // Call the C++ function. 2425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); 2426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtlr(r0); 2427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blr(); 2428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid DirectCEntryStub::GenerateCall(MacroAssembler* masm, Register target) { 2432109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (ABI_USES_FUNCTION_DESCRIPTORS) { 2433109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // AIX/PPC64BE Linux use a function descriptor. 2434109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(target, kPointerSize)); 2435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ip, MemOperand(target, 0)); // Instruction address 2436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 2437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ip needs to be set for DirectCEentryStub::Generate, and also 2438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // for ABI_CALL_VIA_IP. 2439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Move(ip, target); 2440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier intptr_t code = reinterpret_cast<intptr_t>(GetCode().location()); 2443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r0, Operand(code, RelocInfo::CODE_TARGET)); 2444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Call(r0); // Call the stub. 2445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NameDictionaryLookupStub::GenerateNegativeLookup( 2449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Label* miss, Label* done, Register receiver, 2450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register properties, Handle<Name> name, Register scratch0) { 2451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(name->IsUniqueName()); 2452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If names of slots in range from 1 to kProbes - 1 for the hash value are 2453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // not equal to the name and kProbes-th slot is not used (its name is the 2454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // undefined value), it guarantees the hash table doesn't contain the 2455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // property. It's true even if some slots represent deleted properties 2456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (their names are the hole value). 2457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (int i = 0; i < kInlinedProbes; i++) { 2458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // scratch0 points to properties hash. 2459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compute the masked index: (hash + i + i * i) & mask. 2460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register index = scratch0; 2461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Capacity is smi 2^n. 2462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(index, FieldMemOperand(properties, kCapacityOffset)); 2463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subi(index, index, Operand(1)); 2464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral( 2465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ip, Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i))); 2466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(index, index, ip); 2467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Scale the index by multiplying by the entry size. 2469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NameDictionary::kEntrySize == 3); 2470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeftImm(ip, index, Operand(1)); 2471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(index, index, ip); // index *= 3. 2472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register entity_name = scratch0; 2474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Having undefined at this place means the name is not contained. 2475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp = properties; 2476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToPtrArrayOffset(ip, index); 2477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(tmp, properties, ip); 2478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); 2479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!tmp.is(entity_name)); 2481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); 2482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(entity_name, tmp); 2483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(done); 2484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the hole ready for use below: 2486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); 2487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stop if found the property. 2489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Cmpi(entity_name, Operand(Handle<Name>(name)), r0); 2490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(miss); 2491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label good; 2493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(entity_name, tmp); 2494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&good); 2495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if the entry name is not a unique name. 2497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); 2498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(entity_name, FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); 2499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotUniqueNameInstanceType(entity_name, miss); 2500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&good); 2501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore the properties. 2503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(properties, 2504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 2505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int spill_mask = (r0.bit() | r9.bit() | r8.bit() | r7.bit() | r6.bit() | 2508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r5.bit() | r4.bit() | r3.bit()); 2509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 2511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPush(spill_mask); 2512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 2514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r4, Operand(Handle<Name>(name))); 2515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameDictionaryLookupStub stub(masm->isolate(), NEGATIVE_LOOKUP); 2516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallStub(&stub); 2517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r3, Operand::Zero()); 2518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPop(spill_mask); // MultiPop does not touch condition flags 2520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtlr(r0); 2521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(done); 2523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss); 2524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NameDictionaryLookupStub::Generate(MacroAssembler* masm) { 2527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // This stub overrides SometimesSetsUpAFrame() to return false. That means 2528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // we cannot call anything that could cause a GC from this stub. 2529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Registers: 2530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // result: NameDictionary to probe 2531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: key 2532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // dictionary: NameDictionary to probe. 2533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // index: will hold an index of entry if lookup is successful. 2534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // might alias with result_. 2535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Returns: 2536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // result_ is zero if lookup failed, non zero otherwise. 2537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register result = r3; 2539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register dictionary = r3; 2540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register key = r4; 2541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register index = r5; 2542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register mask = r6; 2543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register hash = r7; 2544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register undefined = r8; 2545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register entry_key = r9; 2546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch = r9; 2547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label in_dictionary, maybe_in_dictionary, not_in_dictionary; 2549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(mask, FieldMemOperand(dictionary, kCapacityOffset)); 2551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(mask); 2552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subi(mask, mask, Operand(1)); 2553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwz(hash, FieldMemOperand(key, Name::kHashFieldOffset)); 2555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); 2557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (int i = kInlinedProbes; i < kTotalProbes; i++) { 2559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compute the masked index: (hash + i + i * i) & mask. 2560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Capacity is smi 2^n. 2561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (i > 0) { 2562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Add the probe offset (i + i * i) left shifted to avoid right shifting 2563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the hash in a separate instruction. The value hash + i + i * i is right 2564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // shifted in the following and instruction. 2565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(NameDictionary::GetProbeOffset(i) < 2566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1 << (32 - Name::kHashFieldOffset)); 2567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(index, hash, 2568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift)); 2569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(index, hash); 2571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ srwi(r0, index, Operand(Name::kHashShift)); 2573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(index, mask, r0); 2574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Scale the index by multiplying by the entry size. 2576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NameDictionary::kEntrySize == 3); 2577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeftImm(scratch, index, Operand(1)); 2578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(index, index, scratch); // index *= 3. 2579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeftImm(scratch, index, Operand(kPointerSizeLog2)); 2581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(index, dictionary, scratch); 2582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(entry_key, FieldMemOperand(index, kElementsStartOffset)); 2583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Having undefined at this place means the name is not contained. 2585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(entry_key, undefined); 2586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(¬_in_dictionary); 2587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stop if found the property. 2589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(entry_key, key); 2590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&in_dictionary); 2591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) { 2593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if the entry name is not a unique name. 2594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); 2595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(entry_key, FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); 2596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotUniqueNameInstanceType(entry_key, &maybe_in_dictionary); 2597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&maybe_in_dictionary); 2601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If we are doing negative lookup then probing failure should be 2602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // treated as a lookup success. For positive lookup probing failure 2603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // should be treated as lookup failure. 2604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (mode() == POSITIVE_LOOKUP) { 2605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(result, Operand::Zero()); 2606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&in_dictionary); 2610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(result, Operand(1)); 2611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_in_dictionary); 2614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(result, Operand::Zero()); 2615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 2620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Isolate* isolate) { 2621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs); 2622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub1.GetCode(); 2623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Hydrogen code stubs need stub2 at snapshot time. 2624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreBufferOverflowStub stub2(isolate, kSaveFPRegs); 2625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub2.GetCode(); 2626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Takes the input in 3 registers: address_ value_ and object_. A pointer to 2630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the value has just been written into the object, now this stub makes sure 2631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// we keep the GC informed. The word in the object where the value has been 2632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// written is in the address register. 2633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::Generate(MacroAssembler* masm) { 2634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label skip_to_incremental_noncompacting; 2635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label skip_to_incremental_compacting; 2636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The first two branch instructions are generated with labels so as to 2638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // get the offset fixed up correctly by the bind(Label*) call. We patch 2639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // it back and forth between branch condition True and False 2640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // when we start and stop incremental heap marking. 2641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // See RecordWriteStub::Patch for details. 2642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Clear the bit, branch on True for NOP action initially 2644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ crclr(Assembler::encode_crbit(cr2, CR_LT)); 2645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(&skip_to_incremental_noncompacting, cr2); 2646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(&skip_to_incremental_compacting, cr2); 2647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (remembered_set_action() == EMIT_REMEMBERED_SET) { 2649958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 2650958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler::kReturnAtEnd); 2651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2654958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&skip_to_incremental_noncompacting); 2655958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateIncremental(masm, INCREMENTAL); 2656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&skip_to_incremental_compacting); 2658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateIncremental(masm, INCREMENTAL_COMPACTION); 2659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. 2661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Will be checked in IncrementalMarking::ActivateGeneratedStub. 2662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // patching not required on PPC as the initial path is effectively NOP 2663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { 2667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.Save(masm); 2668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (remembered_set_action() == EMIT_REMEMBERED_SET) { 2670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label dont_need_remembered_set; 2671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0)); 2673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. 2674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.scratch0(), &dont_need_remembered_set); 2675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2676109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfInNewSpace(regs_.object(), regs_.scratch0(), 2677109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch &dont_need_remembered_set); 2678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // First notify the incremental marker if necessary, then update the 2680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // remembered set. 2681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CheckNeedsToInformIncrementalMarker( 2682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); 2683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InformIncrementalMarker(masm); 2684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.Restore(masm); 2685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 2686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler::kReturnAtEnd); 2687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&dont_need_remembered_set); 2689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CheckNeedsToInformIncrementalMarker( 2692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm, kReturnOnNoNeedToInformIncrementalMarker, mode); 2693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InformIncrementalMarker(masm); 2694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.Restore(masm); 2695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { 2700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode()); 2701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int argument_count = 3; 2702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ PrepareCallCFunction(argument_count, regs_.scratch0()); 2703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register address = 2704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r3.is(regs_.address()) ? regs_.scratch0() : regs_.address(); 2705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!address.is(regs_.object())); 2706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!address.is(r3)); 2707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(address, regs_.address()); 2708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r3, regs_.object()); 2709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r4, address); 2710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r5, Operand(ExternalReference::isolate_address(isolate()))); 2711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AllowExternalCallThatCantCauseGC scope(masm); 2713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallCFunction( 2714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::incremental_marking_record_write_function(isolate()), 2715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier argument_count); 2716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode()); 2717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2720958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::CheckNeedsToInformIncrementalMarker( 2721958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, OnNoNeedToInformIncrementalMarker on_no_need, 2722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Mode mode) { 2723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label on_black; 2724958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label need_incremental; 2725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label need_incremental_pop_scratch; 2726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Let's look at the color of the object: If it is not black we don't have 2728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // to inform the incremental marker. 2729958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black); 2730958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2731958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.Restore(masm); 2732958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 2733958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 2734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler::kReturnAtEnd); 2735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2736958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2738958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&on_black); 2740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get the value from the slot. 2742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0)); 2743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (mode == INCREMENTAL_COMPACTION) { 2745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label ensure_not_white; 2746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckPageFlag(regs_.scratch0(), // Contains value. 2748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.scratch1(), // Scratch. 2749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemoryChunk::kEvacuationCandidateMask, eq, 2750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &ensure_not_white); 2751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckPageFlag(regs_.object(), 2753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.scratch1(), // Scratch. 2754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemoryChunk::kSkipEvacuationSlotsRecordingMask, eq, 2755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &need_incremental); 2756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&ensure_not_white); 2758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2759958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2760958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We need extra registers for this, so we push the object and the address 2761958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // register temporarily. 2762958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(regs_.object(), regs_.address()); 2763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfWhite(regs_.scratch0(), // The value. 2764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch regs_.scratch1(), // Scratch. 2765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch regs_.object(), // Scratch. 2766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch regs_.address(), // Scratch. 2767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &need_incremental_pop_scratch); 2768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Pop(regs_.object(), regs_.address()); 2769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.Restore(masm); 2771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 2772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 2773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler::kReturnAtEnd); 2774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2778958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&need_incremental_pop_scratch); 2779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Pop(regs_.object(), regs_.address()); 2780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&need_incremental); 2782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Fall through when we need to inform the incremental marker. 2784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StubFailureTrampolineStub::Generate(MacroAssembler* masm) { 2788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CEntryStub ces(isolate(), 1, kSaveFPRegs); 2789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); 2790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int parameter_count_offset = 27913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch StubFailureTrampolineFrameConstants::kArgumentsLengthOffset; 2792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r4, MemOperand(fp, parameter_count_offset)); 2793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (function_mode() == JS_FUNCTION_STUB_MODE) { 2794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r4, r4, Operand(1)); 2795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); 2797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ slwi(r4, r4, Operand(kPointerSizeLog2)); 2798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(sp, sp, r4); 2799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2802109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { 2803109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (masm->isolate()->function_entry_hook() != NULL) { 2804109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PredictableCodeSizeScope predictable(masm, 2805109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if V8_TARGET_ARCH_PPC64 2806109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 14 * Assembler::kInstrSize); 2807109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else 2808109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 11 * Assembler::kInstrSize); 2809109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif 2810109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ProfileEntryHookStub stub(masm->isolate()); 2811109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mflr(r0); 2812109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r0, ip); 2813109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallStub(&stub); 2814109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(r0, ip); 2815109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mtlr(r0); 2816109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 28178389745919cae02139ddc085a63c00d024269cf2Ben Murdoch} 2818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2820109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ProfileEntryHookStub::Generate(MacroAssembler* masm) { 2821109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The entry hook is a "push lr, ip" instruction, followed by a call. 2822109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int32_t kReturnAddressDistanceFromFunctionStart = 2823109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Assembler::kCallTargetAddressOffset + 3 * Assembler::kInstrSize; 2824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2825109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // This should contain all kJSCallerSaved registers. 2826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const RegList kSavedRegs = kJSCallerSaved | // Caller saved registers. 2827109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch r15.bit(); // Saved stack pointer. 2828f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2829109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We also save lr, so the count here is one higher than the mask indicates. 2830109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int32_t kNumSavedRegs = kNumJSCallerSaved + 2; 2831109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2832109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Save all caller-save registers as this may be called from anywhere. 2833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mflr(ip); 2834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ MultiPush(kSavedRegs | ip.bit()); 2835109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2836109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Compute the function's address for the first argument. 2837109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ subi(r3, ip, Operand(kReturnAddressDistanceFromFunctionStart)); 2838109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2839109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The caller's return address is two slots above the saved temporaries. 2840109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Grab that for the second argument to the hook. 2841109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r4, sp, Operand((kNumSavedRegs + 1) * kPointerSize)); 2842109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2843109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Align the stack if necessary. 2844109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int frame_alignment = masm->ActivationFrameAlignment(); 2845109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (frame_alignment > kPointerSize) { 2846109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r15, sp); 2847109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(base::bits::IsPowerOfTwo32(frame_alignment)); 2848109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment))); 2849109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2850109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2851109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if !defined(USE_SIMULATOR) 2852109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch uintptr_t entry_hook = 2853109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch reinterpret_cast<uintptr_t>(isolate()->function_entry_hook()); 2854109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else 2855109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Under the simulator we need to indirect the entry hook through a 2856109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // trampoline function at a known address. 2857109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); 2858109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference entry_hook = ExternalReference( 2859109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch &dispatcher, ExternalReference::BUILTIN_CALL, isolate()); 2860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2861109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // It additionally takes an isolate as a third parameter 2862109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(r5, Operand(ExternalReference::isolate_address(isolate()))); 2863109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif 2864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2865109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ip, Operand(entry_hook)); 2866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2867109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (ABI_USES_FUNCTION_DESCRIPTORS) { 2868109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(ip, kPointerSize)); 2869109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ip, MemOperand(ip, 0)); 2870109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2871109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ip set above, so nothing more to do for ABI_CALL_VIA_IP. 2872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2873109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // PPC LINUX ABI: 2874109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ li(r0, Operand::Zero()); 2875109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StorePU(r0, MemOperand(sp, -kNumRequiredStackFrameSlots * kPointerSize)); 2876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2877109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Call(ip); 2878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2879109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(sp, sp, Operand(kNumRequiredStackFrameSlots * kPointerSize)); 2880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2881109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Restore the stack pointer if needed. 2882109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (frame_alignment > kPointerSize) { 2883109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(sp, r15); 2884109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2886109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Also pop lr to get Ret(0). 2887109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ MultiPop(kSavedRegs | ip.bit()); 2888109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mtlr(ip); 2889109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 2890109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2893109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochtemplate <class T> 2894109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void CreateArrayDispatch(MacroAssembler* masm, 2895109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AllocationSiteOverrideMode mode) { 2896109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (mode == DISABLE_ALLOCATION_SITES) { 2897109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub(masm->isolate(), GetInitialFastElementsKind(), mode); 2898109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub); 2899109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (mode == DONT_OVERRIDE) { 2900109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int last_index = 2901109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); 2902109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i <= last_index; ++i) { 2903109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 2904109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Cmpi(r6, Operand(kind), r0); 2905109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub(masm->isolate(), kind); 2906109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub, eq); 2907109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2909109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If we reached this point there is a problem. 2910109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Abort(kUnexpectedElementsKindInArrayConstructor); 2911109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 2912109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch UNREACHABLE(); 2913109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 29148389745919cae02139ddc085a63c00d024269cf2Ben Murdoch} 2915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2917109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void CreateArrayDispatchOneArgument(MacroAssembler* masm, 2918109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AllocationSiteOverrideMode mode) { 2919109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r5 - allocation site (if mode != DISABLE_ALLOCATION_SITES) 2920109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r6 - kind (if mode != DISABLE_ALLOCATION_SITES) 2921109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r3 - number of arguments 2922109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r4 - constructor? 2923109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // sp[0] - last argument 2924109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label normal_sequence; 2925109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (mode == DONT_OVERRIDE) { 2926109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 2927109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 2928109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_ELEMENTS == 2); 2929109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); 2930109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_DOUBLE_ELEMENTS == 4); 2931109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); 2932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2933109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // is the low bit set? If so, we are holey and that is good. 2934109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andi(r0, r6, Operand(1)); 2935109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&normal_sequence, cr0); 2936109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2938109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // look at the first argument 2939109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r8, MemOperand(sp, 0)); 2940109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r8, Operand::Zero()); 2941109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&normal_sequence); 2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2943109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (mode == DISABLE_ALLOCATION_SITES) { 2944109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind initial = GetInitialFastElementsKind(); 2945109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind holey_initial = GetHoleyElementsKind(initial); 2946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2947109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArraySingleArgumentConstructorStub stub_holey( 2948109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch masm->isolate(), holey_initial, DISABLE_ALLOCATION_SITES); 2949109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub_holey); 29508389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2951109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&normal_sequence); 2952109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArraySingleArgumentConstructorStub stub(masm->isolate(), initial, 2953109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DISABLE_ALLOCATION_SITES); 2954109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub); 2955109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (mode == DONT_OVERRIDE) { 2956109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We are going to create a holey array, but our kind is non-holey. 2957109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Fix kind and retry (only if we have an allocation site in the slot). 2958109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r6, r6, Operand(1)); 29598389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2960109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 2961109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r8, FieldMemOperand(r5, 0)); 2962109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex); 2963109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(eq, kExpectedAllocationSite); 2964109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2966109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Save the resulting elements kind in type info. We can't just store r6 2967109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // in the AllocationSite::transition_info field because elements kind is 2968109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // restricted to a portion of the field...upper bits need to be left alone. 2969109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 2970109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r7, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset)); 2971109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AddSmiLiteral(r7, r7, Smi::FromInt(kFastElementsKindPackedToHoley), r0); 2972109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r7, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset), 2973109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch r0); 2974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2975109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&normal_sequence); 2976109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int last_index = 2977109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); 2978109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i <= last_index; ++i) { 2979109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 2980109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(r0, Operand(kind)); 2981109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(r6, r0); 2982109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArraySingleArgumentConstructorStub stub(masm->isolate(), kind); 2983109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub, eq); 2984109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2986109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If we reached this point there is a problem. 2987109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Abort(kUnexpectedElementsKindInArrayConstructor); 2988109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 2989109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch UNREACHABLE(); 2990109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2991109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2994109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochtemplate <class T> 2995109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { 2996109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int to_index = 2997109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); 2998109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i <= to_index; ++i) { 2999109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 3000109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub(isolate, kind); 3001109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stub.GetCode(); 3002109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { 3003109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub1(isolate, kind, DISABLE_ALLOCATION_SITES); 3004109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stub1.GetCode(); 3005109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3006109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3007109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 301013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) { 3011109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( 3012109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch isolate); 301313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ArrayNArgumentsConstructorStub stub(isolate); 301413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch stub.GetCode(); 3015109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kinds[2] = {FAST_ELEMENTS, FAST_HOLEY_ELEMENTS}; 3016109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i < 2; i++) { 3017109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // For internal arrays we only need a few things 3018109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]); 3019109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stubh1.GetCode(); 3020109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]); 3021109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stubh2.GetCode(); 3022109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3023109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3024109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3025109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3026109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ArrayConstructorStub::GenerateDispatchToArrayStub( 3027109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MacroAssembler* masm, AllocationSiteOverrideMode mode) { 3028c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label not_zero_case, not_one_case; 3029c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ cmpi(r3, Operand::Zero()); 3030c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ bne(¬_zero_case); 3031c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 3032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3033c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ bind(¬_zero_case); 3034c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ cmpi(r3, Operand(1)); 3035c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ bgt(¬_one_case); 3036c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CreateArrayDispatchOneArgument(masm, mode); 3037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3038c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ bind(¬_one_case); 3039c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ArrayNArgumentsConstructorStub stub(masm->isolate()); 3040c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ TailCallStub(&stub); 3041109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3043958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3044109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ArrayConstructorStub::Generate(MacroAssembler* masm) { 3045109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 3046109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r3 : argc (only if argument_count() == ANY) 3047109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r4 : constructor 3048109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r5 : AllocationSite or undefined 3049109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r6 : new target 3050109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- sp[0] : return address 3051109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- sp[4] : last argument 3052109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 3053958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3054109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 3055109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The array construct code is only set for the global and natives 3056109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // builtin Array functions which always have maps. 3057958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3058109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Initial map for the builtin Array function should be a map. 3059109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r7, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); 3060109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Will both indicate a NULL and a Smi. 3061109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TestIfSmi(r7, r0); 3062109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0); 3063109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareObjectType(r7, r7, r8, MAP_TYPE); 3064109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 3065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3066109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We should either have undefined in r5 or a valid AllocationSite 3067109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertUndefinedOrAllocationSite(r5, r7); 3068109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3070109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Enter the context of the Array function. 3071109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); 3072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3073109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label subclassing; 3074109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(r6, r4); 3075109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&subclassing); 3076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3077109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label no_info; 3078109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Get the elements kind and case on that. 3079109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(r5, Heap::kUndefinedValueRootIndex); 3080109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&no_info); 3081958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3082109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r6, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset)); 3083109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiUntag(r6); 3084109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 3085109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ And(r6, r6, Operand(AllocationSite::ElementsKindBits::kMask)); 3086109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); 3087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3088109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&no_info); 3089109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); 3090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3091109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&subclassing); 3092c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2)); 3093c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ StorePX(r4, MemOperand(sp, r0)); 3094c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ addi(r3, r3, Operand(3)); 3095109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r6, r5); 3096109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpToExternalReference(ExternalReference(Runtime::kNewArray, isolate())); 3097109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3100109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InternalArrayConstructorStub::GenerateCase(MacroAssembler* masm, 3101109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kind) { 3102109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpli(r3, Operand(1)); 3103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3104109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArrayNoArgumentConstructorStub stub0(isolate(), kind); 3105109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub0, lt); 3106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 310713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ArrayNArgumentsConstructorStub stubN(isolate()); 3108109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stubN, gt); 3109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3110109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (IsFastPackedElementsKind(kind)) { 3111109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We might need to create a holey array 3112109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // look at the first argument 3113109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r6, MemOperand(sp, 0)); 3114109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r6, Operand::Zero()); 3115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3116109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArraySingleArgumentConstructorStub stub1_holey( 3117109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch isolate(), GetHoleyElementsKind(kind)); 3118109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub1_holey, ne); 3119f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 3120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3121109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArraySingleArgumentConstructorStub stub1(isolate(), kind); 3122109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub1); 3123109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 31258389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 3126109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InternalArrayConstructorStub::Generate(MacroAssembler* masm) { 3127109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 3128109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r3 : argc 3129109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r4 : constructor 3130109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- sp[0] : return address 3131109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- sp[4] : last argument 3132109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 3133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3134109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 3135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The array construct code is only set for the global and natives 3136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // builtin Array functions which always have maps. 3137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Initial map for the builtin Array function should be a map. 3139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r6, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); 3140109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Will both indicate a NULL and a Smi. 3141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TestIfSmi(r6, r0); 3142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0); 3143109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareObjectType(r6, r6, r7, MAP_TYPE); 3144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 3145f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 3146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Figure out the right elements kind 3148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r6, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); 3149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load the map's "bit field 2" into |result|. 3150109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lbz(r6, FieldMemOperand(r6, Map::kBitField2Offset)); 3151109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Retrieve elements_kind from bit field 2. 3152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ DecodeField<Map::ElementsKindBits>(r6); 3153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 3155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label done; 3156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r6, Operand(FAST_ELEMENTS)); 3157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&done); 3158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r6, Operand(FAST_HOLEY_ELEMENTS)); 3159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(eq, kInvalidElementsKindForInternalArrayOrInternalPackedArray); 3160109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done); 3161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3163109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label fast_elements_case; 3164109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r6, Operand(FAST_ELEMENTS)); 3165109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&fast_elements_case); 3166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateCase(masm, FAST_HOLEY_ELEMENTS); 3167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&fast_elements_case); 3169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateCase(masm, FAST_ELEMENTS); 31708389745919cae02139ddc085a63c00d024269cf2Ben Murdoch} 3171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic int AddressOffset(ExternalReference ref0, ExternalReference ref1) { 3173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return ref0.address() - ref1.address(); 3174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Calls an API function. Allocates HandleScope, extracts returned value 3178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// from handle and propagates exceptions. Restores context. stack_space 3179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// - space to be unwound on exit (includes the call JS arguments space and 3180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// the additional space allocated for the fast call). 3181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void CallApiFunctionAndReturn(MacroAssembler* masm, 3182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register function_address, 3183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference thunk_ref, 3184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int stack_space, 3185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand* stack_space_operand, 3186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand return_value_operand, 3187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand* context_restore_operand) { 3188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate* isolate = masm->isolate(); 3189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference next_address = 3190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::handle_scope_next_address(isolate); 3191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kNextOffset = 0; 3192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kLimitOffset = AddressOffset( 3193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::handle_scope_limit_address(isolate), next_address); 3194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kLevelOffset = AddressOffset( 3195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::handle_scope_level_address(isolate), next_address); 3196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Additional parameter is the address of the actual callback. 3198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(function_address.is(r4) || function_address.is(r5)); 3199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch = r6; 3200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch, Operand(ExternalReference::is_profiling_address(isolate))); 3202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lbz(scratch, MemOperand(scratch, 0)); 3203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(scratch, Operand::Zero()); 3204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 3206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch, Operand(thunk_ref)); 3207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, scratch, function_address, scratch); 3208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 3209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label profiler_disabled; 3210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label end_profiler_check; 3211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&profiler_disabled); 3212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch, Operand(thunk_ref)); 3213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&end_profiler_check); 3214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&profiler_disabled); 3215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(scratch, function_address); 3216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&end_profiler_check); 3217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Allocate HandleScope in callee-save registers. 3220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r17 - next_address 3221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r14 - next_address->kNextOffset 3222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r15 - next_address->kLimitOffset 3223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r16 - next_address->kLevelOffset 3224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r17, Operand(next_address)); 3225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r14, MemOperand(r17, kNextOffset)); 3226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r15, MemOperand(r17, kLimitOffset)); 3227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lwz(r16, MemOperand(r17, kLevelOffset)); 3228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addi(r16, r16, Operand(1)); 3229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ stw(r16, MemOperand(r17, kLevelOffset)); 3230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_log_timer_events) { 3232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope frame(masm, StackFrame::MANUAL); 3233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushSafepointRegisters(); 3234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PrepareCallCFunction(1, r3); 3235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); 3236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallCFunction(ExternalReference::log_enter_external_function(isolate), 3237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1); 3238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopSafepointRegisters(); 3239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Native call returns to the DirectCEntry stub which redirects to the 3242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // return address pushed on stack (could have moved after GC). 3243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // DirectCEntry stub itself is generated early and never moves. 3244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DirectCEntryStub stub(isolate); 3245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stub.GenerateCall(masm, scratch); 3246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_log_timer_events) { 3248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope frame(masm, StackFrame::MANUAL); 3249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushSafepointRegisters(); 3250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PrepareCallCFunction(1, r3); 3251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); 3252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallCFunction(ExternalReference::log_leave_external_function(isolate), 3253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1); 3254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopSafepointRegisters(); 3255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label promote_scheduled_exception; 3258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label delete_allocated_handles; 3259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label leave_exit_frame; 3260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label return_value_loaded; 3261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // load value from ReturnValue 3263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r3, return_value_operand); 3264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&return_value_loaded); 3265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // No more valid handles (the result handle was the last one). Restore 3266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // previous handle scope. 3267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(r14, MemOperand(r17, kNextOffset)); 3268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (__ emit_debug_code()) { 3269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lwz(r4, MemOperand(r17, kLevelOffset)); 3270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, r16); 3271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall); 3272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ subi(r16, r16, Operand(1)); 3274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ stw(r16, MemOperand(r17, kLevelOffset)); 3275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r0, MemOperand(r17, kLimitOffset)); 3276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r15, r0); 3277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&delete_allocated_handles); 3278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Leave the API exit frame. 3280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&leave_exit_frame); 3281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool restore_context = context_restore_operand != NULL; 3282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (restore_context) { 3283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(cp, *context_restore_operand); 3284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // LeaveExitFrame expects unwind space to be in a register. 3286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (stack_space_operand != NULL) { 3287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lwz(r14, *stack_space_operand); 3288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 3289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r14, Operand(stack_space)); 3290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LeaveExitFrame(false, r14, !restore_context, stack_space_operand != NULL); 3292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if the function scheduled an exception. 3294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r14, Heap::kTheHoleValueRootIndex); 3295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r15, Operand(ExternalReference::scheduled_exception_address(isolate))); 3296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r15, MemOperand(r15)); 3297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r14, r15); 3298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&promote_scheduled_exception); 3299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blr(); 3301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Re-throw by promoting a scheduled exception. 3303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&promote_scheduled_exception); 3304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kPromoteScheduledException); 3305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // HandleScope limit has changed. Delete allocated extensions. 3307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&delete_allocated_handles); 3308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(r15, MemOperand(r17, kLimitOffset)); 3309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r14, r3); 3310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PrepareCallCFunction(1, r15); 3311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); 3312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate), 3313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1); 3314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r3, r14); 3315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&leave_exit_frame); 3316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 33183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid CallApiCallbackStub::Generate(MacroAssembler* masm) { 3319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------- S t a t e ------------- 3320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r3 : callee 3321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r7 : call_data 3322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r5 : holder 3323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r4 : api_function_address 3324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- cp : context 3325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- 3326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- sp[0] : last argument 3327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- ... 3328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- sp[(argc - 1)* 4] : first argument 3329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- sp[argc * 4] : receiver 3330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------------------------------- 3331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register callee = r3; 3333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register call_data = r7; 3334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder = r5; 3335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register api_function_address = r4; 3336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register context = cp; 3337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier typedef FunctionCallbackArguments FCA; 3339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kContextSaveIndex == 6); 3341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kCalleeIndex == 5); 3342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kDataIndex == 4); 3343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kReturnValueOffset == 3); 3344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 3345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kIsolateIndex == 1); 3346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kHolderIndex == 0); 3347bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(FCA::kNewTargetIndex == 7); 3348bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(FCA::kArgsLength == 8); 3349bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3350bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // new target 3351bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 3352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // context save 3354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(context); 33553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (!is_lazy()) { 3356109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // load context from callee 3357109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(context, FieldMemOperand(callee, JSFunction::kContextOffset)); 3358109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // callee 3361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(callee); 3362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // call data 3364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(call_data); 3365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch = call_data; 33673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (!call_data_undefined()) { 3368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 3369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // return value 3371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(scratch); 3372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // return value default 3373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(scratch); 3374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // isolate 3375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch, Operand(ExternalReference::isolate_address(masm->isolate()))); 3376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(scratch); 3377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // holder 3378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(holder); 3379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Prepare arguments. 3381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(scratch, sp); 3382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Allocate the v8::Arguments structure in the arguments' space since 3384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // it's not controlled by GC. 3385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // PPC LINUX ABI: 3386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 3387bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Create 4 extra slots on stack: 3388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // [0] space for DirectCEntryStub's LR save 3389bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // [1-3] FunctionCallbackInfo 3390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch const int kApiStackSpace = 4; 3391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kFunctionCallbackInfoOffset = 3392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (kStackFrameExtraParamSlot + 1) * kPointerSize; 3393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameScope frame_scope(masm, StackFrame::MANUAL); 3395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ EnterExitFrame(false, kApiStackSpace); 3396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!api_function_address.is(r3) && !scratch.is(r3)); 3398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3 = FunctionCallbackInfo& 3399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Arguments is after the return address. 3400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addi(r3, sp, Operand(kFunctionCallbackInfoOffset)); 3401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // FunctionCallbackInfo::implicit_args_ 3402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(scratch, MemOperand(r3, 0 * kPointerSize)); 34033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // FunctionCallbackInfo::values_ 34043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ addi(ip, scratch, Operand((FCA::kArgsLength - 1 + argc()) * kPointerSize)); 34053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ StoreP(ip, MemOperand(r3, 1 * kPointerSize)); 34063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // FunctionCallbackInfo::length_ = argc 34073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ li(ip, Operand(argc())); 34083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ stw(ip, MemOperand(r3, 2 * kPointerSize)); 3409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference thunk_ref = 3411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::invoke_function_callback(masm->isolate()); 3412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AllowExternalCallThatCantCauseGC scope(masm); 3414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemOperand context_restore_operand( 3415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier fp, (2 + FCA::kContextSaveIndex) * kPointerSize); 3416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stores return the first js argument 3417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int return_value_offset = 0; 34183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (is_store()) { 3419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return_value_offset = 2 + FCA::kArgsLength; 3420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 3421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return_value_offset = 2 + FCA::kReturnValueOffset; 3422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemOperand return_value_operand(fp, return_value_offset * kPointerSize); 3424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int stack_space = 0; 3425bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MemOperand length_operand = 3426bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize); 3427bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MemOperand* stack_space_operand = &length_operand; 34283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch stack_space = argc() + FCA::kArgsLength + 1; 34293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch stack_space_operand = NULL; 3430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space, 3431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stack_space_operand, return_value_operand, 3432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &context_restore_operand); 3433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CallApiGetterStub::Generate(MacroAssembler* masm) { 3437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int arg0Slot = 0; 3438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int accessorInfoSlot = 0; 3439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int apiStackSpace = 0; 3440bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Build v8::PropertyCallbackInfo::args_ array on the stack and push property 3441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // name below the exit frame to make GC aware of them. 3442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0); 3443bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1); 3444bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2); 3445bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3); 3446bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4); 3447bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5); 3448bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6); 3449bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7); 3450bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3451bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register receiver = ApiGetterDescriptor::ReceiverRegister(); 3452bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register holder = ApiGetterDescriptor::HolderRegister(); 3453bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register callback = ApiGetterDescriptor::CallbackRegister(); 3454bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register scratch = r7; 3455bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!AreAliased(receiver, holder, callback, scratch)); 3456bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3457bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register api_function_address = r5; 3458bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3459bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(receiver); 3460bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Push data from AccessorInfo. 3461bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kDataOffset)); 3462bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(scratch); 3463bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 3464bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(scratch, scratch); 3465bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(scratch, Operand(ExternalReference::isolate_address(isolate()))); 3466bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(scratch, holder); 3467c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Push(Smi::kZero); // should_throw_on_error -> false 3468bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kNameOffset)); 3469bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(scratch); 3470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // v8::PropertyCallbackInfo::args_ array and name handle. 3472109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; 3473109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3474109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load address of v8::PropertyAccessorInfo::args_ array and name handle. 3475109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r3, sp); // r3 = Handle<Name> 3476109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r4, r3, Operand(1 * kPointerSize)); // r4 = v8::PCI::args_ 3477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// If ABI passes Handles (pointer-sized struct) in a register: 3479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// 3480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Create 2 extra slots on stack: 3481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// [0] space for DirectCEntryStub's LR save 3482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// [1] AccessorInfo& 3483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// 3484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Otherwise: 3485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// 3486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Create 3 extra slots on stack: 3487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// [0] space for DirectCEntryStub's LR save 3488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// [1] copy of Handle (first arg) 3489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// [2] AccessorInfo& 3490109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (ABI_PASSES_HANDLES_IN_REGS) { 3491109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch accessorInfoSlot = kStackFrameExtraParamSlot + 1; 3492109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch apiStackSpace = 2; 3493109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 3494109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch arg0Slot = kStackFrameExtraParamSlot + 1; 3495109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch accessorInfoSlot = arg0Slot + 1; 3496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch apiStackSpace = 3; 3497109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameScope frame_scope(masm, StackFrame::MANUAL); 3500109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ EnterExitFrame(false, apiStackSpace); 3501f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 3502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!ABI_PASSES_HANDLES_IN_REGS) { 3503109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // pass 1st arg by reference 3504109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r3, MemOperand(sp, arg0Slot * kPointerSize)); 3505109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r3, sp, Operand(arg0Slot * kPointerSize)); 3506109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3508109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Create v8::PropertyCallbackInfo object on the stack and initialize 3509109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // it's args_ field. 3510109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, MemOperand(sp, accessorInfoSlot * kPointerSize)); 3511109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r4, sp, Operand(accessorInfoSlot * kPointerSize)); 3512109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r4 = v8::PropertyCallbackInfo& 3513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference thunk_ref = 3515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::invoke_accessor_getter_callback(isolate()); 3516109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3517bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kJsGetterOffset)); 3518bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadP(api_function_address, 3519bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch FieldMemOperand(scratch, Foreign::kForeignAddressOffset)); 3520bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3521109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // +3 is to skip prolog, return address and name handle. 3522109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MemOperand return_value_operand( 3523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize); 3524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, 3525109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kStackUnwindSpace, NULL, return_value_operand, NULL); 3526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef __ 3529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 3530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 3531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif // V8_TARGET_ARCH_PPC 3533