code-stubs-ppc.cc revision bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8
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 24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void InitializeArrayConstructorDescriptor( 26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Isolate* isolate, CodeStubDescriptor* descriptor, 27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int constant_stack_parameter_count) { 28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Address deopt_handler = 29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Runtime::FunctionForId(Runtime::kArrayConstructor)->entry; 30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (constant_stack_parameter_count == 0) { 32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier descriptor->Initialize(deopt_handler, constant_stack_parameter_count, 33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier JS_FUNCTION_STUB_MODE); 34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier descriptor->Initialize(r3, deopt_handler, constant_stack_parameter_count, 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JS_FUNCTION_STUB_MODE); 37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void InitializeInternalArrayConstructorDescriptor( 42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Isolate* isolate, CodeStubDescriptor* descriptor, 43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int constant_stack_parameter_count) { 44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Address deopt_handler = 45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry; 46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (constant_stack_parameter_count == 0) { 48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier descriptor->Initialize(deopt_handler, constant_stack_parameter_count, 49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier JS_FUNCTION_STUB_MODE); 50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier descriptor->Initialize(r3, deopt_handler, constant_stack_parameter_count, 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JS_FUNCTION_STUB_MODE); 53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid ArraySingleArgumentConstructorStub::InitializeDescriptor( 58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CodeStubDescriptor* descriptor) { 59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InitializeArrayConstructorDescriptor(isolate(), descriptor, 1); 60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid ArrayNArgumentsConstructorStub::InitializeDescriptor( 64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CodeStubDescriptor* descriptor) { 65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InitializeArrayConstructorDescriptor(isolate(), descriptor, -1); 66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { 703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Address deopt_handler = Runtime::FunctionForId(Runtime::kArrayPush)->entry; 713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch descriptor->Initialize(r3, deopt_handler, -1, JS_FUNCTION_STUB_MODE); 723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InternalArraySingleArgumentConstructorStub::InitializeDescriptor( 75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CodeStubDescriptor* descriptor) { 76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1); 77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InternalArrayNArgumentsConstructorStub::InitializeDescriptor( 81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CodeStubDescriptor* descriptor) { 82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1); 83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define __ ACCESS_MASM(masm) 87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, 89109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Condition cond); 90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs, 91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs, Label* lhs_not_nan, 92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* slow, bool strict); 93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs, 94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs); 95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm, 98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference miss) { 99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Update the static counter each time a new code stub is generated. 100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate()->counters()->code_stubs()->Increment(); 101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor(); 103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int param_count = descriptor.GetRegisterParameterCount(); 104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call the runtime system in a fresh internal frame. 106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(param_count == 0 || 108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch r3.is(descriptor.GetRegisterParameter(param_count - 1))); 109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Push arguments 110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (int i = 0; i < param_count; ++i) { 111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(descriptor.GetRegisterParameter(i)); 112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallExternalReference(miss, param_count); 114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid DoubleToIStub::Generate(MacroAssembler* masm) { 121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label out_of_range, only_low, negate, done, fastpath_done; 122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register input_reg = source(); 123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register result_reg = destination(); 124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(is_truncating()); 125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int double_offset = offset(); 127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Immediate values for this stub fit in instructions, so it's safe to use ip. 129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch = GetRegisterThatIsNotOneOf(input_reg, result_reg); 130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch_low = 131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch); 132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch_high = 133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low); 134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DoubleRegister double_scratch = kScratchDoubleReg; 135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(scratch); 137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Account for saved regs if input is sp. 138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (input_reg.is(sp)) double_offset += kPointerSize; 139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!skip_fastpath()) { 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load double input. 142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(double_scratch, MemOperand(input_reg, double_offset)); 143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Do fast-path convert from double to int. 145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ConvertDoubleToInt64(double_scratch, 146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if !V8_TARGET_ARCH_PPC64 147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scratch, 148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif 149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier result_reg, d0); 150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Test for overflow 152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64 153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TestIfInt32(result_reg, r0); 154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#else 155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TestIfInt32(scratch, result_reg, r0); 156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif 157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&fastpath_done); 158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(scratch_high, scratch_low); 161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Account for saved regs if input is sp. 162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (input_reg.is(sp)) double_offset += 2 * kPointerSize; 163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwz(scratch_high, 165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemOperand(input_reg, double_offset + Register::kExponentOffset)); 166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwz(scratch_low, 167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemOperand(input_reg, double_offset + Register::kMantissaOffset)); 168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ExtractBitMask(scratch, scratch_high, HeapNumber::kExponentMask); 170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load scratch with exponent - 1. This is faster than loading 171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // with exponent because Bias + 1 = 1024 which is a *PPC* immediate value. 172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(HeapNumber::kExponentBias + 1 == 1024); 173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subi(scratch, scratch, Operand(HeapNumber::kExponentBias + 1)); 174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If exponent is greater than or equal to 84, the 32 less significant 175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits), 176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the result is 0. 177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare exponent with 84 (compare exponent - 1 with 83). 178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(scratch, Operand(83)); 179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bge(&out_of_range); 180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If we reach this code, 31 <= exponent <= 83. 182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // So, we don't have to handle cases where 0 <= exponent <= 20 for 183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // which we would need to shift right the high part of the mantissa. 184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Scratch contains exponent - 1. 185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load scratch with 52 - exponent (load with 51 - (exponent - 1)). 186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subfic(scratch, scratch, Operand(51)); 187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(scratch, Operand::Zero()); 188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ble(&only_low); 189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 21 <= exponent <= 51, shift scratch_low and scratch_high 190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // to generate the result. 191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ srw(scratch_low, scratch_low, scratch); 192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Scratch contains: 52 - exponent. 193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We needs: exponent - 20. 194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20. 195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subfic(scratch, scratch, Operand(32)); 196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ExtractBitMask(result_reg, scratch_high, HeapNumber::kMantissaMask); 197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Set the implicit 1 before the mantissa part in scratch_high. 198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(HeapNumber::kMantissaBitsInTopWord >= 16); 199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ oris(result_reg, result_reg, 200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(1 << ((HeapNumber::kMantissaBitsInTopWord) - 16))); 201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ slw(r0, result_reg, scratch); 202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(result_reg, scratch_low, r0); 203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&negate); 204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&out_of_range); 206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(result_reg, Operand::Zero()); 207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&done); 208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&only_low); 210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 52 <= exponent <= 83, shift only scratch_low. 211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // On entry, scratch contains: 52 - exponent. 212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ neg(scratch, scratch); 213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ slw(result_reg, scratch_low, scratch); 214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&negate); 216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If input was positive, scratch_high ASR 31 equals 0 and 217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // scratch_high LSR 31 equals zero. 218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // New result = (result eor 0) + 0 = result. 219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If the input was negative, we have to negate the result. 220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1. 221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // New result = (result eor 0xffffffff) + 1 = 0 - result. 222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ srawi(r0, scratch_high, 31); 223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64 224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ srdi(r0, r0, Operand(32)); 225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif 226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ xor_(result_reg, result_reg, r0); 227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ srwi(r0, scratch_high, Operand(31)); 228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(result_reg, result_reg, r0); 229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&done); 231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Pop(scratch_high, scratch_low); 232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&fastpath_done); 234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(scratch); 235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Handle the case where the lhs and rhs are the same object. 241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Equality is almost reflexive (everything but NaN), so this is a test 242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// for "identity and not NaN". 243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, 244109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Condition cond) { 245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label not_identical; 246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label heap_number, return_equal; 247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r3, r4); 248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(¬_identical); 249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), 251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // so we do the second best thing - test it ourselves. 252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // They are both equal and they are not both Smis so both of them are not 253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Smis. If it's not a heap number, then return equal. 254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond == lt || cond == gt) { 255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call runtime on identical JSObjects. 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r3, r7, r7, FIRST_JS_RECEIVER_TYPE); 257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bge(slow); 258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call runtime on identical symbols since we need to throw a TypeError. 259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(r7, Operand(SYMBOL_TYPE)); 260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(slow); 261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call runtime on identical SIMD values since we must throw a TypeError. 262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(r7, Operand(SIMD128_VALUE_TYPE)); 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(slow); 264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE); 266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&heap_number); 267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Comparing JS objects with <=, >= is complicated. 268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond != eq) { 269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(r7, Operand(FIRST_JS_RECEIVER_TYPE)); 270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bge(slow); 271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call runtime on identical symbols since we need to throw a TypeError. 272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(r7, Operand(SYMBOL_TYPE)); 273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(slow); 274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call runtime on identical SIMD values since we must throw a TypeError. 275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(r7, Operand(SIMD128_VALUE_TYPE)); 276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(slow); 277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Normally here we fall through to return_equal, but undefined is 278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // special: (undefined == undefined) == true, but 279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (undefined <= undefined) == false! See ECMAScript 11.8.5. 280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond == le || cond == ge) { 281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r7, Operand(ODDBALL_TYPE)); 282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&return_equal); 283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); 284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r3, r5); 285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&return_equal); 286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond == le) { 287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // undefined <= undefined should fail. 288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(GREATER)); 289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // undefined >= undefined should fail. 291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(LESS)); 292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&return_equal); 299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond == lt) { 300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(GREATER)); // Things aren't less than themselves. 301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (cond == gt) { 302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(LESS)); // Things aren't greater than themselves. 303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(EQUAL)); // Things are <=, >=, ==, === themselves. 305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For less and greater we don't have to check for NaN since the result of 309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // x < x is false regardless. For the others here is some code to check 310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // for NaN. 311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond != lt && cond != gt) { 312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&heap_number); 313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // It is a heap number, so return non-equal if it's NaN and equal if it's 314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // not NaN. 315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The representation of NaN values has all exponent bits (52..62) set, 317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // and not all mantissa bits (0..51) clear. 318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Read top bits of double representation (second word of value). 319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwz(r5, FieldMemOperand(r3, HeapNumber::kExponentOffset)); 320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Test that exponent bits are all set. 321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(HeapNumber::kExponentMask == 0x7ff00000u); 322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ExtractBitMask(r6, r5, HeapNumber::kExponentMask); 323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpli(r6, Operand(0x7ff)); 324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&return_equal); 325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Shift out flag and all exponent bits, retaining only mantissa. 327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ slwi(r5, r5, Operand(HeapNumber::kNonMantissaBitsInTopWord)); 328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Or with all low-bits of mantissa. 329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwz(r6, FieldMemOperand(r3, HeapNumber::kMantissaOffset)); 330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(r3, r6, r5); 331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r3, Operand::Zero()); 332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For equal we already have the right value in r3: Return zero (equal) 333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // if all bits in mantissa are zero (it's an Infinity) and non-zero if 334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // not (it's a NaN). For <= and >= we need to load r0 with the failing 335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // value if it's a NaN. 336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cond != eq) { 337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r4, Operand((cond == le) ? GREATER : LESS)); 339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, r3, r3, r4); 340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // All-zero means Infinity means equal. 342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(eq); 343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (cond == le) { 344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(GREATER)); // NaN <= NaN should fail. 345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(LESS)); // NaN >= NaN should fail. 347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // No fall through here. 353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_identical); 355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// See comment at call site. 359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs, 360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs, Label* lhs_not_nan, 361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* slow, bool strict) { 362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label rhs_is_smi; 365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(rhs, &rhs_is_smi); 366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Lhs is a Smi. Check whether the rhs is a heap number. 368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(rhs, r6, r7, HEAP_NUMBER_TYPE); 369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (strict) { 370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If rhs is not a number and lhs is a Smi then strict equality cannot 371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // succeed. Return non-equal 372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If rhs is r3 then there is already a non zero value in it. 373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!rhs.is(r3)) { 374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label skip; 375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&skip); 376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(NOT_EQUAL)); 377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&skip); 379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(ne); 381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Smi compared non-strictly with a non-Smi non-heap-number. Call 384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the runtime. 385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(slow); 386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Lhs is a smi, rhs is a number. 389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Convert lhs to a double in d7. 390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToDouble(d7, lhs); 391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the double from rhs, tagged HeapNumber r3, to d6. 392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We now have both loaded as doubles but we can skip the lhs nan check 395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // since it's a smi. 396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(lhs_not_nan); 397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&rhs_is_smi); 399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Rhs is a smi. Check whether the non-smi lhs is a heap number. 400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(lhs, r7, r7, HEAP_NUMBER_TYPE); 401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (strict) { 402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If lhs is not a number and rhs is a smi then strict equality cannot 403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // succeed. Return non-equal. 404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If lhs is r3 then there is already a non zero value in it. 405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!lhs.is(r3)) { 406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label skip; 407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&skip); 408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(NOT_EQUAL)); 409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&skip); 411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(ne); 413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Smi compared non-strictly with a non-smi non-heap-number. Call 416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the runtime. 417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(slow); 418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Rhs is a smi, lhs is a heap number. 421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the double from lhs, tagged HeapNumber r4, to d7. 422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Convert rhs to a double in d6. 424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToDouble(d6, rhs); 425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Fall through to both_loaded_as_doubles. 426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// See comment at call site. 430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs, 431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs) { 432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If either operand is a JS object or an oddball value, then they are 435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // not equal since their pointers are different. 436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // There is no test for undetectability in strict equality. 437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label first_non_object; 439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get the type of the first operand into r5 and compare it with 440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // FIRST_JS_RECEIVER_TYPE. 441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(rhs, r5, r5, FIRST_JS_RECEIVER_TYPE); 442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(&first_non_object); 443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return non-zero (r3 is not zero) 445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label return_not_equal; 446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&return_not_equal); 447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&first_non_object); 450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for oddballs: true, false, null, undefined. 451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r5, Operand(ODDBALL_TYPE)); 452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&return_not_equal); 453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(lhs, r6, r6, FIRST_JS_RECEIVER_TYPE); 455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bge(&return_not_equal); 456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for oddballs: true, false, null, undefined. 458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r6, Operand(ODDBALL_TYPE)); 459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&return_not_equal); 460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Now that we have the types we might as well check for 462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // internalized-internalized. 463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(r5, r5, r6); 465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r5, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&return_not_equal, cr0); 467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// See comment at call site. 471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, Register lhs, 472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs, 473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* both_loaded_as_doubles, 474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* not_heap_numbers, Label* slow) { 475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(rhs, r6, r5, HEAP_NUMBER_TYPE); 478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(not_heap_numbers); 479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r5, FieldMemOperand(lhs, HeapObject::kMapOffset)); 480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r5, r6); 481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(slow); // First was a heap number, second wasn't. Go slow case. 482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Both are heap numbers. Load them up then jump to the code we have 484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // for that. 485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(both_loaded_as_doubles); 489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// Fast negative check for internalized-to-internalized equality or receiver 4923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// equality. Also handles the undetectable receiver to null/undefined 4933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// comparison. 494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, 495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register lhs, Register rhs, 496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* possible_strings, 497109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label* runtime_call) { 498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5 is object type of rhs. 5013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label object_test, return_equal, return_unequal, undetectable; 502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r5, Operand(kIsNotStringMask)); 504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&object_test, cr0); 505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r5, Operand(kIsNotInternalizedMask)); 506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(possible_strings, cr0); 507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(lhs, r6, r6, FIRST_NONSTRING_TYPE); 508109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bge(runtime_call); 509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r6, Operand(kIsNotInternalizedMask)); 510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(possible_strings, cr0); 511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 512109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Both are internalized. We already checked they weren't the same pointer so 513109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // they are not equal. Return non-equal by returning the non-zero object 514109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // pointer in r3. 515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&object_test); 518109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r5, FieldMemOperand(lhs, HeapObject::kMapOffset)); 519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r6, FieldMemOperand(rhs, HeapObject::kMapOffset)); 520109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lbz(r7, FieldMemOperand(r5, Map::kBitFieldOffset)); 521109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lbz(r8, FieldMemOperand(r6, Map::kBitFieldOffset)); 522109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andi(r0, r7, Operand(1 << Map::kIsUndetectable)); 523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&undetectable, cr0); 524109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andi(r0, r8, Operand(1 << Map::kIsUndetectable)); 525109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&return_unequal, cr0); 526109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 527109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareInstanceType(r5, r5, FIRST_JS_RECEIVER_TYPE); 528109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ blt(runtime_call); 529109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareInstanceType(r6, r6, FIRST_JS_RECEIVER_TYPE); 530109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ blt(runtime_call); 531109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 532109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&return_unequal); 533109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Return non-equal by returning the non-zero object pointer in r3. 534109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 535109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 536109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&undetectable); 537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andi(r0, r8, Operand(1 << Map::kIsUndetectable)); 538109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&return_unequal, cr0); 5393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 5403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // If both sides are JSReceivers, then the result is false according to 5413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // the HTML specification, which says that only comparisons with null or 5423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // undefined are affected by special casing for document.all. 5433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CompareInstanceType(r5, r5, ODDBALL_TYPE); 5443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ beq(&return_equal); 5453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CompareInstanceType(r6, r6, ODDBALL_TYPE); 5463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bne(&return_unequal); 5473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 5483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bind(&return_equal); 549109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ li(r3, Operand(EQUAL)); 550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, 555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch, 556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompareICState::State expected, 557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* fail) { 558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label ok; 559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (expected == CompareICState::SMI) { 560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(input, fail); 561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (expected == CompareICState::NUMBER) { 562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(input, &ok); 563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, 564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DONT_DO_SMI_CHECK); 565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We could be strict about internalized/non-internalized here, but as long as 567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // hydrogen doesn't care, the stub doesn't have to care either. 568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&ok); 569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// On entry r4 and r5 are the values to be compared. 573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// On exit r3 is 0, positive or negative to indicate the result of 574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the comparison. 575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateGeneric(MacroAssembler* masm) { 576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register lhs = r4; 577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register rhs = r3; 578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Condition cc = GetCondition(); 579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompareICStub_CheckInputType(masm, lhs, r5, left(), &miss); 582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompareICStub_CheckInputType(masm, rhs, r6, right(), &miss); 583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label slow; // Call builtin. 585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label not_smis, both_loaded_as_doubles, lhs_not_nan; 586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label not_two_smis, smi_done; 588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(r5, r4, r3); 589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r5, ¬_two_smis); 590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r4); 591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r3); 592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ sub(r3, r4, r3); 593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_two_smis); 595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // NOTICE! This code is only reached after a smi-fast-case check, so 597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // it is certain that at least one operand isn't a smi. 598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Handle the case where the objects are identical. Either returns the answer 600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // or goes to slow. Only falls through if the objects were not identical. 601109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitIdenticalObjectComparison(masm, &slow, cc); 602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If either is a Smi (we know that not both are), then they can only 604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // be strictly equal if the other is a HeapNumber. 605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0)); 607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(r5, lhs, rhs); 608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r5, ¬_smis); 609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // One operand is a smi. EmitSmiNonsmiComparison generates code that can: 610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 1) Return the answer. 611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 2) Go to slow. 612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 3) Fall through to both_loaded_as_doubles. 613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 4) Jump to lhs_not_nan. 614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // In cases 3 and 4 we have found out we were dealing with a number-number 615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // comparison. The double values of the numbers have been loaded 616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // into d7 and d6. 617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict()); 618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&both_loaded_as_doubles); 620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The arguments have been converted to doubles and stored in d6 and d7 621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&lhs_not_nan); 622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label no_nan; 623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fcmpu(d7, d6); 624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label nan, equal, less_than; 626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bunordered(&nan); 627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(EQUAL == 0); 629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r4, Operand(GREATER)); 630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r5, Operand(LESS)); 631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, r3, r0, r4); 632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(lt, r3, r5, r3); 633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&equal); 636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blt(&less_than); 637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(GREATER)); 638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&equal); 640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(EQUAL)); 641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&less_than); 643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(LESS)); 644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&nan); 648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If one of the sides was a NaN then the v flag is set. Load r3 with 649958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // whatever it takes to make the comparison fail, since comparisons with NaN 650958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // always fail. 651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cc == lt || cc == le) { 652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(GREATER)); 653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 654958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r3, Operand(LESS)); 655958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_smis); 659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // At this point we know we are dealing with two different objects, 660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // and neither of them is a Smi. The objects are in rhs_ and lhs_. 661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (strict()) { 662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // This returns non-equal for some object types, or falls through if it 663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // was not lucky. 664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitStrictTwoHeapObjectCompare(masm, lhs, rhs); 665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label check_for_internalized_strings; 668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label flat_string_check; 669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for heap-number-heap-number comparison. Can jump to slow case, 670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // or load both doubles into r3, r4, r5, r6 and jump to the code that handles 671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // that case. If the inputs are not doubles then jumps to 672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // check_for_internalized_strings. 673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // In this case r5 will contain the type of rhs_. Never falls through. 674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitCheckForTwoHeapNumbers(masm, lhs, rhs, &both_loaded_as_doubles, 675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &check_for_internalized_strings, 676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &flat_string_check); 677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&check_for_internalized_strings); 679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // In the strict case the EmitStrictTwoHeapObjectCompare already took care of 680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // internalized strings. 681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cc == eq && !strict()) { 682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Returns an answer for two internalized strings or two detectable objects. 683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Otherwise jumps to string case or not both strings case. 684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Assumes that r5 is the type of rhs_ on entry. 685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitCheckForInternalizedStringsOrObjects(masm, lhs, rhs, &flat_string_check, 686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &slow); 687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for both being sequential one-byte strings, 690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // and inline if that is the case. 691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&flat_string_check); 692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNonSmisNotBothSequentialOneByteStrings(lhs, rhs, r5, r6, &slow); 694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r5, 696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r6); 697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cc == eq) { 698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringHelper::GenerateFlatOneByteStringEquals(masm, lhs, rhs, r5, r6); 699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringHelper::GenerateCompareFlatOneByteStrings(masm, lhs, rhs, r5, r6, r7); 701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Never falls through to here. 703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&slow); 705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cc == eq) { 707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 709109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(lhs, rhs); 710109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual); 711109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 712109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Turn true into 0 and false into some non-zero value. 713109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(EQUAL == 0); 714109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r4, Heap::kTrueValueRootIndex); 715109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ sub(r3, r3, r4); 716109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 718109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(lhs, rhs); 719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int ncr; // NaN compare result 720958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cc == lt || cc == le) { 721958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ncr = GREATER; 722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(cc == gt || cc == ge); // remaining cases 724958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ncr = LESS; 725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(ncr)); 727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r3); 728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // tagged as a small integer. 731109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallRuntime(Runtime::kCompare); 732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 733958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 736958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 738958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We don't allow a GC during a store buffer overflow so there is no need to 741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // store the registers in any particular way, but we do have to store and 742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // restore them. 743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPush(kJSCallerSaved | r0.bit()); 745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (save_doubles()) { 746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ MultiPushDoubles(kCallerSavedDoubles); 747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int argument_count = 1; 749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int fp_argument_count = 0; 750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register scratch = r4; 751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AllowExternalCallThatCantCauseGC scope(masm); 753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); 754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(ExternalReference::isolate_address(isolate()))); 755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallCFunction(ExternalReference::store_buffer_overflow_function(isolate()), 756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier argument_count); 757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (save_doubles()) { 758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ MultiPopDoubles(kCallerSavedDoubles); 759958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 760958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPop(kJSCallerSaved | r0.bit()); 761958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtlr(r0); 762958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 763958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 765958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 766958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreRegistersStateStub::Generate(MacroAssembler* masm) { 767958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ PushSafepointRegisters(); 768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blr(); 769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RestoreRegistersStateStub::Generate(MacroAssembler* masm) { 773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ PopSafepointRegisters(); 774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blr(); 775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 778958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MathPowStub::Generate(MacroAssembler* masm) { 779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register base = r4; 780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register exponent = MathPowTaggedDescriptor::exponent(); 781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(exponent.is(r5)); 782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register heapnumbermap = r8; 783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register heapnumber = r3; 784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const DoubleRegister double_base = d1; 785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const DoubleRegister double_exponent = d2; 786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const DoubleRegister double_result = d3; 787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const DoubleRegister double_scratch = d0; 788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register scratch = r11; 789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register scratch2 = r10; 790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label call_runtime, done, int_exponent; 792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (exponent_type() == ON_STACK) { 793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label base_is_smi, unpack_exponent; 794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The exponent and base are supplied as arguments on the stack. 795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // This can only happen if the stub is called from non-optimized code. 796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load input parameters from stack to double registers. 797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(base, MemOperand(sp, 1 * kPointerSize)); 798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(exponent, MemOperand(sp, 0 * kPointerSize)); 799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); 801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); 803958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch, FieldMemOperand(base, JSObject::kMapOffset)); 804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(scratch, heapnumbermap); 805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&call_runtime); 806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); 808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&unpack_exponent); 809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&base_is_smi); 811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ConvertIntToDouble(scratch, double_base); 812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&unpack_exponent); 813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); 816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(scratch, heapnumbermap); 817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&call_runtime); 818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(double_exponent, 820958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(exponent, HeapNumber::kValueOffset)); 821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (exponent_type() == TAGGED) { 822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Base is already in double_base. 823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(double_exponent, 826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(exponent, HeapNumber::kValueOffset)); 827958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 829958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (exponent_type() != INTEGER) { 830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Detect integer exponents stored as double. 831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TryDoubleToInt32Exact(scratch, double_exponent, scratch2, 832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier double_scratch); 833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&int_exponent); 834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (exponent_type() == ON_STACK) { 836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Detect square root case. Crankshaft detects constant +/-0.5 at 837958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // compile time and uses DoMathPowHalf instead. We then skip this check 838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // for non-constant cases of +/-0.5 as these hardly occur. 839958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label not_plus_half, not_minus_inf1, not_minus_inf2; 840958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Test for 0.5. 842958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadDoubleLiteral(double_scratch, 0.5, scratch); 843958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fcmpu(double_exponent, double_scratch); 844958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(¬_plus_half); 845958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 846958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Calculates square root of base. Check for the special case of 847958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). 848958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadDoubleLiteral(double_scratch, -V8_INFINITY, scratch); 849958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fcmpu(double_base, double_scratch); 850958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(¬_minus_inf1); 851958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fneg(double_result, double_scratch); 852958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&done); 853958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_minus_inf1); 854958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 855958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Add +0 to convert -0 to +0. 856958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fadd(double_scratch, double_base, kDoubleRegZero); 857958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fsqrt(double_result, double_scratch); 858958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&done); 859958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 860958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_plus_half); 861958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadDoubleLiteral(double_scratch, -0.5, scratch); 862958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fcmpu(double_exponent, double_scratch); 863958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&call_runtime); 864958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 865958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Calculates square root of base. Check for the special case of 866958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). 867958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadDoubleLiteral(double_scratch, -V8_INFINITY, scratch); 868958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fcmpu(double_base, double_scratch); 869958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(¬_minus_inf2); 870958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fmr(double_result, kDoubleRegZero); 871958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&done); 872958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_minus_inf2); 873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 874958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Add +0 to convert -0 to +0. 875958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fadd(double_scratch, double_base, kDoubleRegZero); 876958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadDoubleLiteral(double_result, 1.0, scratch); 877958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fsqrt(double_scratch, double_scratch); 878958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fdiv(double_result, double_result, double_scratch); 879958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&done); 880958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 881958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 882958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 883958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 884958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 885958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AllowExternalCallThatCantCauseGC scope(masm); 886958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ PrepareCallCFunction(0, 2, scratch); 887958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MovToFloatParameters(double_base, double_exponent); 888958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallCFunction( 889958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::power_double_double_function(isolate()), 0, 2); 890958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 891958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(r0); 892958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtlr(r0); 893958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MovFromFloatResult(double_result); 894958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&done); 895958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 896958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 897958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Calculate power with integer exponent. 898958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&int_exponent); 899958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 900958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get two copies of exponent in the registers scratch and exponent. 901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (exponent_type() == INTEGER) { 902958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(scratch, exponent); 903958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 904958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Exponent has previously been stored into scratch as untagged integer. 905958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(exponent, scratch); 906958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fmr(double_scratch, double_base); // Back up base. 908958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(scratch2, Operand(1)); 909958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ConvertIntToDouble(scratch2, double_result); 910958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 911958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get absolute value of exponent. 912958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(scratch, Operand::Zero()); 913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ neg(scratch2, scratch); 915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(lt, scratch, scratch2, scratch); 916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label positive_exponent; 918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bge(&positive_exponent); 919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ neg(scratch, scratch); 920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&positive_exponent); 921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 923958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label while_true, no_carry, loop_end; 924958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&while_true); 925958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(scratch2, scratch, Operand(1)); 926958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&no_carry, cr0); 927958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fmul(double_result, double_result, double_scratch); 928958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&no_carry); 929958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftRightArithImm(scratch, scratch, 1, SetRC); 930958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&loop_end, cr0); 931958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fmul(double_scratch, double_scratch, double_scratch); 932958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&while_true); 933958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&loop_end); 934958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 935958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(exponent, Operand::Zero()); 936958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bge(&done); 937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 938958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(scratch2, Operand(1)); 939958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ConvertIntToDouble(scratch2, double_scratch); 940958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fdiv(double_result, double_scratch, double_result); 941958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Test whether result is zero. Bail out to check for subnormal result. 942958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. 943958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fcmpu(double_result, kDoubleRegZero); 944958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&done); 945958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // double_exponent may not containe the exponent value if the input was a 946958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // smi. We set it with exponent value before bailing out. 947958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ConvertIntToDouble(exponent, double_exponent); 948958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 949958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Returning or bailing out. 950958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (exponent_type() == ON_STACK) { 951958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The arguments are still on the stack. 952958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&call_runtime); 953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kMathPowRT); 954958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The stub is called from non-optimized code, which expects the result 956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // as heap number in exponent. 957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&done); 958958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ AllocateHeapNumber(heapnumber, scratch, scratch2, heapnumbermap, 959958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &call_runtime); 960958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ stfd(double_result, 961958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); 962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(heapnumber.is(r3)); 963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(2); 964958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 965958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 966958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 967958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 968958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AllowExternalCallThatCantCauseGC scope(masm); 969958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ PrepareCallCFunction(0, 2, scratch); 970958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MovToFloatParameters(double_base, double_exponent); 971958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallCFunction( 972958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::power_double_double_function(isolate()), 0, 2); 973958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 974958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(r0); 975958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtlr(r0); 976958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MovFromFloatResult(double_result); 977958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 978958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&done); 979958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 980958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 981958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 982958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 983958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 984958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool CEntryStub::NeedsImmovableCode() { return true; } 985958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 986958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 987958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CEntryStub::GenerateAheadOfTime(isolate); 989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 990958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 991958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CreateWeakCellStub::GenerateAheadOfTime(isolate); 994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier BinaryOpICStub::GenerateAheadOfTime(isolate); 995958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreRegistersStateStub::GenerateAheadOfTime(isolate); 996958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier RestoreRegistersStateStub::GenerateAheadOfTime(isolate); 997958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StoreFastElementStub::GenerateAheadOfTime(isolate); 999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TypeofStub::GenerateAheadOfTime(isolate); 1000958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1001958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { 1004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreRegistersStateStub stub(isolate); 1005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub.GetCode(); 1006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1009958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RestoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { 1010958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier RestoreRegistersStateStub stub(isolate); 1011958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub.GetCode(); 1012958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1013958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1014958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1015958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CodeStub::GenerateFPStubs(Isolate* isolate) { 1016958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Generate if not already in cache. 1017958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SaveFPRegsMode mode = kSaveFPRegs; 1018958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CEntryStub(isolate, 1, mode).GetCode(); 1019958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreBufferOverflowStub(isolate, mode).GetCode(); 1020958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate->set_fp_stubs_generated(true); 1021958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1022958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1023958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1024958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 1025958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CEntryStub stub(isolate, 1, kDontSaveFPRegs); 1026958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub.GetCode(); 1027958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1028958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1029958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1030958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CEntryStub::Generate(MacroAssembler* masm) { 1031958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Called from JavaScript; parameters are on stack as if calling JS function. 1032958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: number of arguments including receiver 1033958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: pointer to builtin function 1034958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // fp: frame pointer (restored after C call) 1035958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // sp: stack pointer (restored as callee's sp after C call) 1036958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // cp: current context (C callee-saved) 1037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If argv_in_register(): 1039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r5: pointer to the first argument 1040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ProfileEntryHookStub::MaybeCallEntryHook(masm); 1041958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1042958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r15, r4); 1043958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (argv_in_register()) { 1045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Move argv into the correct register. 1046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r4, r5); 1047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compute the argv pointer. 1049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ShiftLeftImm(r4, r3, Operand(kPointerSizeLog2)); 1050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(r4, r4, sp); 1051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ subi(r4, r4, Operand(kPointerSize)); 1052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1053958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1054958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Enter the exit frame that transitions from JavaScript to C++. 1055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameScope scope(masm, StackFrame::MANUAL); 1056958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1057958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Need at least one extra slot for return address location. 1058958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int arg_stack_space = 1; 1059958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1060958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Pass buffer for return value on stack if necessary 1061109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch bool needs_return_buffer = 1062109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch result_size() > 2 || 1063109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch (result_size() == 2 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS); 1064109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (needs_return_buffer) { 1065109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch arg_stack_space += result_size(); 1066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1067958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1068958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ EnterExitFrame(save_doubles(), arg_stack_space); 1069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Store a copy of argc in callee-saved registers for later. 1071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r14, r3); 1072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3, r14: number of arguments including receiver (C callee-saved) 1074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: pointer to the first argument 1075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r15: pointer to builtin function (C callee-saved) 1076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Result returned in registers or stack, depending on result size and ABI. 1078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register isolate_reg = r5; 1080109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (needs_return_buffer) { 1081109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The return value is a non-scalar value. 1082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Use frame storage reserved by calling function to pass return 1083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // buffer as implicit first argument. 1084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r5, r4); 1085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r4, r3); 1086958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize)); 1087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate_reg = r6; 1088958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call C built-in. 1091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate()))); 1092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register target = r15; 1094109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (ABI_USES_FUNCTION_DESCRIPTORS) { 1095109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // AIX/PPC64BE Linux use a function descriptor. 1096109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize)); 1097109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ip, MemOperand(r15, 0)); // Instruction address 1098109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch target = ip; 1099109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (ABI_CALL_VIA_IP) { 1100109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Move(ip, r15); 1101109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch target = ip; 1102109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // To let the GC traverse the return address of the exit frames, we need to 1105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // know where the return address is. The CEntryStub is unmovable, so 1106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // we can store the address on the stack to be able to find it again and 1107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // we never have to restore it, because it will not change. 1108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label after_call; 1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov_label_addr(r0, &after_call); 1110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); 1111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Call(target); 1112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&after_call); 1113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If return value is on the stack, pop it to registers. 1115109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (needs_return_buffer) { 1116109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (result_size() > 2) __ LoadP(r5, MemOperand(r3, 2 * kPointerSize)); 1117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r4, MemOperand(r3, kPointerSize)); 1118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, MemOperand(r3)); 1119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check result for exception sentinel. 1122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label exception_returned; 1123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareRoot(r3, Heap::kExceptionRootIndex); 1124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&exception_returned); 1125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that there is no pending exception, otherwise we 1127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // should have returned the exception sentinel. 1128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (FLAG_debug_code) { 1129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label okay; 1130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_exception_address( 1131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingExceptionAddress, isolate()); 1132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1133109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(r6, Operand(pending_exception_address)); 1134109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r6, MemOperand(r6)); 1135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); 1136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Cannot use check here as it attempts to generate call into runtime. 1137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&okay); 1138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ stop("Unexpected pending exception"); 1139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&okay); 1140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Exit C frame and return. 1143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3:r4: result 1144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // sp: stack pointer 1145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // fp: frame pointer 1146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register argc; 1147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (argv_in_register()) { 1148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We don't want to pop arguments so set argc to no_reg. 1149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch argc = no_reg; 1150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r14: still holds argc (callee-saved). 1152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch argc = r14; 1153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LeaveExitFrame(save_doubles(), argc, true); 1155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blr(); 1156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Handling of exception. 1158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&exception_returned); 1159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_handler_context_address( 1161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingHandlerContextAddress, isolate()); 1162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_handler_code_address( 1163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingHandlerCodeAddress, isolate()); 1164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_handler_offset_address( 1165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingHandlerOffsetAddress, isolate()); 1166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_handler_fp_address( 1167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingHandlerFPAddress, isolate()); 1168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_handler_sp_address( 1169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate::kPendingHandlerSPAddress, isolate()); 1170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Ask the runtime for help to determine the handler. This will set r3 to 1172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // contain the current pending exception, don't clobber it. 1173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler, 1174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate()); 1175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PrepareCallCFunction(3, 0, r3); 1178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand::Zero()); 1179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r4, Operand::Zero()); 1180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r5, Operand(ExternalReference::isolate_address(isolate()))); 1181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallCFunction(find_handler, 3); 1182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Retrieve the handler context, SP and FP. 1185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(cp, Operand(pending_handler_context_address)); 1186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(cp, MemOperand(cp)); 1187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(sp, Operand(pending_handler_sp_address)); 1188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(sp, MemOperand(sp)); 1189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(fp, Operand(pending_handler_fp_address)); 1190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(fp, MemOperand(fp)); 1191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the handler is a JS frame, restore the context to the frame. Note that 1193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the context will be set to (cp == 0) for non-JS frames. 1194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label skip; 1195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(cp, Operand::Zero()); 1196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&skip); 1197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&skip); 1199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compute the handler entry address and jump to it. 1201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ConstantPoolUnavailableScope constant_pool_unavailable(masm); 1202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r4, Operand(pending_handler_code_address)); 1203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r4, MemOperand(r4)); 1204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r5, Operand(pending_handler_offset_address)); 1205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r5, MemOperand(r5)); 1206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addi(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start 1207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_enable_embedded_constant_pool) { 1208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(r4); 1209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(ip, r4, r5); 1211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(ip); 1212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid JSEntryStub::Generate(MacroAssembler* masm) { 1216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: code entry 1217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: function 1218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: receiver 1219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: argc 1220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // [sp+0]: argv 1221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label invoke, handler_entry, exit; 1223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Called from C 1225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ function_descriptor(); 1226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ProfileEntryHookStub::MaybeCallEntryHook(masm); 1228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // PPC LINUX ABI: 1230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // preserve LR in pre-reserved slot in caller's frame 1231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 1232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize)); 1233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Save callee saved registers on the stack. 1235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPush(kCalleeSaved); 1236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Save callee-saved double registers. 1238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ MultiPushDoubles(kCalleeSavedDoubles); 1239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Set up the reserved register for 0.0. 1240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadDoubleLiteral(kDoubleRegZero, 0.0, r0); 1241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Push a frame with special values setup to mark it as an entry frame. 1243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: code entry 1244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: function 1245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: receiver 1246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: argc 1247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r7: argv 1248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r0, Operand(-1)); // Push a bad frame pointer to fail if it is used. 1249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 1250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_enable_embedded_constant_pool) { 1251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(kConstantPoolRegister, Operand::Zero()); 1252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(kConstantPoolRegister); 1253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int marker = type(); 1255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r0, Smi::FromInt(marker)); 1256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 1257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 1258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Save copies of the top frame descriptor on the stack. 1259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 1260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r0, MemOperand(r8)); 1261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 1262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Set up frame pointer for the frame to be pushed. 1264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 1265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If this is the outermost JS call, set js_entry_sp value. 1267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label non_outermost_js; 1268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate()); 1269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r8, Operand(ExternalReference(js_entry_sp))); 1270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r9, MemOperand(r8)); 1271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r9, Operand::Zero()); 1272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&non_outermost_js); 1273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(fp, MemOperand(r8)); 1274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)); 1275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label cont; 1276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&cont); 1277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&non_outermost_js); 1278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)); 1279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&cont); 1280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(ip); // frame-type 1281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Jump to a faked try block that does the invoke, with a faked catch 1283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // block that sets the pending exception. 1284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&invoke); 1285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&handler_entry); 1287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier handler_offset_ = handler_entry.pos(); 1288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Caught exception: Store result (exception) in the pending exception 1289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // field in the JSEnv and return a failure sentinel. Coming in here the 1290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // fp will be invalid because the PushStackHandler below sets it to 0 to 1291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // signal the existence of the JSEntry frame. 1292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate()))); 1294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r3, MemOperand(ip)); 1296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(r3, Heap::kExceptionRootIndex); 1297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&exit); 1298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Invoke: Link this frame into the handler chain. 1300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&invoke); 1301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Must preserve r3-r7. 1302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushStackHandler(); 1303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If an exception not caught by another handler occurs, this handler 1304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // returns control to the code after the b(&invoke) above, which 1305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // restores all kCalleeSaved registers (including cp and fp) to their 1306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // saved values before returning a failure to C. 1307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Clear any pending exceptions. 1309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r8, Operand(isolate()->factory()->the_hole_value())); 1310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate()))); 1312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r8, MemOperand(ip)); 1313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Invoke the function by calling through JS entry trampoline builtin. 1315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Notice that we cannot store a reference to the trampoline code directly in 1316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // this stub, because runtime stubs are not traversed when doing GC. 1317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Expected registers by Builtins::JSEntryTrampoline 1319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: code entry 1320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: function 1321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: receiver 1322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: argc 1323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r7: argv 1324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (type() == StackFrame::ENTRY_CONSTRUCT) { 1325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline, 1326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate()); 1327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(construct_entry)); 1328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference entry(Builtins::kJSEntryTrampoline, isolate()); 1330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(entry)); 1331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(ip, MemOperand(ip)); // deref address 1333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Branch and link to JSEntryTrampoline. 1335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the address points to the start of the code object, skip the header 1336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); 1337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtctr(ip); 1338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bctrl(); // make the call 1339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Unlink this frame from the handler chain. 1341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopStackHandler(); 1342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&exit); // r3 holds result 1344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if the current stack frame is marked as the outermost JS frame. 1345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label non_outermost_js_2; 1346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(r8); 1347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CmpSmiLiteral(r8, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME), r0); 1348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&non_outermost_js_2); 1349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r9, Operand::Zero()); 1350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r8, Operand(ExternalReference(js_entry_sp))); 1351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r9, MemOperand(r8)); 1352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&non_outermost_js_2); 1353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore the top frame descriptors from the stack. 1355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(r6); 1356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 1357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r6, MemOperand(ip)); 1358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Reset the stack to the callee saved registers. 1360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 1361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restore callee-saved double registers. 1363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ MultiPopDoubles(kCalleeSavedDoubles); 1364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restore callee-saved registers. 1366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPop(kCalleeSaved); 1367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Return 1369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize)); 1370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mtlr(r0); 1371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blr(); 1372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FunctionPrototypeStub::Generate(MacroAssembler* masm) { 1376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 1377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register receiver = LoadDescriptor::ReceiverRegister(); 1378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Ensure that the vector and slot registers won't be clobbered before 1379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // calling the miss handler. 1380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!AreAliased(r7, r8, LoadWithVectorDescriptor::VectorRegister(), 1381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadWithVectorDescriptor::SlotRegister())); 1382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r7, 1384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch r8, &miss); 1385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 1386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PropertyAccessCompiler::TailCallBuiltin( 1387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC)); 1388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid LoadIndexedStringStub::Generate(MacroAssembler* masm) { 1392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return address is in lr. 1393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 1394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register receiver = LoadDescriptor::ReceiverRegister(); 1396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register index = LoadDescriptor::NameRegister(); 1397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch = r8; 1398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register result = r3; 1399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!scratch.is(receiver) && !scratch.is(index)); 1400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()) && 1401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result.is(LoadWithVectorDescriptor::SlotRegister())); 1402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // StringCharAtGenerator doesn't use the result register until it's passed 1404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the different miss possibilities. If it did, we would have a conflict 1405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // when FLAG_vector_ics is true. 1406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringCharAtGenerator char_at_generator(receiver, index, scratch, result, 1407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &miss, // When not a string. 1408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &miss, // When not a number. 1409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &miss, // When index out of range. 1410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STRING_INDEX_IS_ARRAY_INDEX, 1411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier RECEIVER_IS_STRING); 1412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier char_at_generator.GenerateFast(masm); 1413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 1414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StubRuntimeCallHelper call_helper; 1416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); 1417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 1419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PropertyAccessCompiler::TailCallBuiltin( 1420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); 1421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1424109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid RegExpExecStub::Generate(MacroAssembler* masm) { 1425109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Just jump directly to runtime if native RegExp is not selected at compile 1426109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// time or if regexp entry in generated code is turned off runtime switch or 1427109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// at compilation. 1428109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#ifdef V8_INTERPRETED_REGEXP 1429109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallRuntime(Runtime::kRegExpExec); 1430109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else // V8_INTERPRETED_REGEXP 1431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1432109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Stack frame on entry. 1433109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // sp[0]: last_match_info (expected JSArray) 1434109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // sp[4]: previous index 1435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // sp[8]: subject string 1436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // sp[12]: JSRegExp object 1437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kLastMatchInfoOffset = 0 * kPointerSize; 1439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kPreviousIndexOffset = 1 * kPointerSize; 1440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kSubjectOffset = 2 * kPointerSize; 1441109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kJSRegExpOffset = 3 * kPointerSize; 1442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1443109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label runtime, br_over, encoding_type_UC16; 1444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1445109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Allocation of registers for this function. These are in callee save 1446109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // registers and will be preserved by the call to the native RegExp code, as 1447109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // this code is called using the normal C calling convention. When calling 1448109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // directly from generated code the native RegExp code will not do a GC and 1449109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // therefore the content of these registers are safe to use after the call. 1450109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register subject = r14; 1451109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register regexp_data = r15; 1452109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register last_match_info_elements = r16; 1453109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register code = r17; 1454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1455109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Ensure register assigments are consistent with callee save masks 1456109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(subject.bit() & kCalleeSaved); 1457109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(regexp_data.bit() & kCalleeSaved); 1458109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(last_match_info_elements.bit() & kCalleeSaved); 1459109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(code.bit() & kCalleeSaved); 1460f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1461109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Ensure that a RegExp stack is allocated. 1462109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference address_of_regexp_stack_memory_address = 1463109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference::address_of_regexp_stack_memory_address(isolate()); 1464109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference address_of_regexp_stack_memory_size = 1465109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference::address_of_regexp_stack_memory_size(isolate()); 1466109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(r3, Operand(address_of_regexp_stack_memory_size)); 1467109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, MemOperand(r3, 0)); 1468109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r3, Operand::Zero()); 1469109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&runtime); 1470f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check that the first argument is a JSRegExp object. 1472109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, MemOperand(sp, kJSRegExpOffset)); 1473109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(r3, &runtime); 1474109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareObjectType(r3, r4, r4, JS_REGEXP_TYPE); 1475109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&runtime); 1476f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1477109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check that the RegExp has been compiled (data contains a fixed array). 1478109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(regexp_data, FieldMemOperand(r3, JSRegExp::kDataOffset)); 1479109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 1480109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TestIfSmi(regexp_data, r0); 1481109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected, cr0); 1482109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareObjectType(regexp_data, r3, r3, FIXED_ARRAY_TYPE); 1483109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected); 1484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1486109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // regexp_data: RegExp data (FixedArray) 1487109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 1488109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); 1489109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // DCHECK(Smi::FromInt(JSRegExp::IRREGEXP) < (char *)0xffffu); 1490109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpSmiLiteral(r3, Smi::FromInt(JSRegExp::IRREGEXP), r0); 1491109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&runtime); 1492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1493109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // regexp_data: RegExp data (FixedArray) 1494109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check that the number of captures fit in the static offsets vector buffer. 1495109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r5, 1496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 1497109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check (number_of_captures + 1) * 2 <= offsets vector size 1498109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Or number_of_captures * 2 <= offsets vector size - 2 1499109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // SmiToShortArrayOffset accomplishes the multiplication by 2 and 1500109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // SmiUntag (which is a nop for 32-bit). 1501109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToShortArrayOffset(r5, r5); 1502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); 1503109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpli(r5, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2)); 1504109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bgt(&runtime); 1505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1506109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reset offset for possibly sliced string. 1507109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ li(r11, Operand::Zero()); 1508109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(subject, MemOperand(sp, kSubjectOffset)); 1509109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(subject, &runtime); 1510109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r6, subject); // Make a copy of the original subject string. 1511109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // subject: subject string 1512109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r6: subject string 1513109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // regexp_data: RegExp data (FixedArray) 1514109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Handle subject string according to its encoding and representation: 1515109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (1) Sequential string? If yes, go to (4). 1516109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (2) Sequential or cons? If not, go to (5). 1517109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (3) Cons string. If the string is flat, replace subject with first string 1518109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // and go to (1). Otherwise bail out to runtime. 1519109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (4) Sequential string. Load regexp code according to encoding. 1520109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (E) Carry on. 1521109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch /// [...] 1522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Deferred code at the end of the stub: 1524109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (5) Long external string? If not, go to (7). 1525109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (6) External string. Make it, offset-wise, look like a sequential string. 1526109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Go to (4). 1527109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (7) Short external string or not a string? If yes, bail out to runtime. 1528109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (8) Sliced string. Replace subject with parent. Go to (1). 1529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1530109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */, 1531109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch not_seq_nor_cons /* 5 */, not_long_external /* 7 */; 1532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1533109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&check_underlying); 1534109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset)); 1535109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset)); 1536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (1) Sequential string? If yes, go to (4). 1538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1539109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT((kIsNotStringMask | kStringRepresentationMask | 1540109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kShortExternalStringMask) == 0x93); 1541109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andi(r4, r3, Operand(kIsNotStringMask | kStringRepresentationMask | 1542109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kShortExternalStringMask)); 1543109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); 1544109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&seq_string, cr0); // Go to (4). 1545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1546109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (2) Sequential or cons? If not, go to (5). 1547109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kConsStringTag < kExternalStringTag); 1548109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 1549109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 1550109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 1551109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kExternalStringTag < 0xffffu); 1552109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r4, Operand(kExternalStringTag)); 1553109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bge(¬_seq_nor_cons); // Go to (5). 1554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1555109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (3) Cons string. Check that it's flat. 1556109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Replace subject with first string and reload instance type. 1557109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, FieldMemOperand(subject, ConsString::kSecondOffset)); 1558109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(r3, Heap::kempty_stringRootIndex); 1559109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&runtime); 1560109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); 1561109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&check_underlying); 1562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1563109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (4) Sequential string. Load regexp code according to encoding. 1564f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&seq_string); 1565f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // subject: sequential subject string (or look-alike, external string) 1566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: original subject string 1567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load previous index and check range before r6 is overwritten. We have to 1568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // use r6 instead of subject here because subject might have been only made 1569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // to look like a sequential string when it actually is an external string. 1570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r4, MemOperand(sp, kPreviousIndexOffset)); 1571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r4, &runtime); 1572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r6, FieldMemOperand(r6, String::kLengthOffset)); 1573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpl(r6, r4); 1574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ble(&runtime); 1575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r4); 1576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(4 == kOneByteStringTag); 1578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kTwoByteStringTag == 0); 1579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kStringEncodingMask == 4); 1580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ExtractBitMask(r6, r3, kStringEncodingMask, SetRC); 1581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&encoding_type_UC16, cr0); 1582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(code, 1583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset)); 1584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&br_over); 1585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&encoding_type_UC16); 1586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(code, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); 1587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&br_over); 1588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (E) Carry on. String handling is done. 1590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // code: irregexp code 1591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the irregexp code has been generated for the actual string 1592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // encoding. If it has, the field contains a code object otherwise it contains 1593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // a smi (code flushing support). 1594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(code, &runtime); 1595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: previous index 1597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: encoding of subject string (1 if one_byte, 0 if two_byte); 1598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // code: Address of generated regexp code 1599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // subject: Subject string 1600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // regexp_data: RegExp data (FixedArray) 1601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // All checks done. Now push arguments for native regexp code. 1602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 1, r3, r5); 1603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Isolates: note we add an additional parameter here (isolate pointer). 1605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int kRegExpExecuteArguments = 10; 1606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int kParameterRegisters = 8; 1607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); 1608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stack pointer now points to cell where return address is to be written. 1610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Arguments are before that on the stack or in registers. 1611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 10 (in stack parameter area): Pass current isolate address. 1613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(ExternalReference::isolate_address(isolate()))); 1614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r3, MemOperand(sp, (kStackFrameExtraParamSlot + 1) * kPointerSize)); 1615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 9 is a dummy that reserves the space used for 1617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the return address added by the ExitFrame in native calls. 1618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 8 (r10): Indicate that this is a direct call from JavaScript. 1620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r10, Operand(1)); 1621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 7 (r9): Start (high end) of backtracking stack memory area. 1623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(address_of_regexp_stack_memory_address)); 1624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, MemOperand(r3, 0)); 1625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r5, Operand(address_of_regexp_stack_memory_size)); 1626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r5, MemOperand(r5, 0)); 1627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(r9, r3, r5); 1628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 6 (r8): Set the number of capture registers to zero to force 1630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // global egexps to behave as non-global. This does not affect non-global 1631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // regexps. 1632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(r8, Operand::Zero()); 1633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 5 (r7): static offsets vector buffer. 1635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov( 1636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r7, 1637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(ExternalReference::address_of_static_offsets_vector(isolate()))); 1638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For arguments 4 (r6) and 3 (r5) get string length, calculate start of data 1640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // and calculate the shift of the index (0 for one-byte and 1 for two-byte). 1641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r18, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); 1642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ xori(r6, r6, Operand(1)); 1643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the length from the original subject string from the previous stack 1644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // frame. Therefore we have to use fp, which points exactly to two pointer 1645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // sizes below the previous sp. (Because creating a new stack frame pushes 1646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) 1647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); 1648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If slice offset is not 0, load the length from the original sliced string. 1649958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 4, r6: End of string data 1650958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 3, r5: Start of string data 1651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Prepare start and end index of the input. 1652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeft_(r11, r11, r6); 1653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(r11, r18, r11); 1654958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeft_(r5, r4, r6); 1655958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(r5, r11, r5); 1656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r18, FieldMemOperand(subject, String::kLengthOffset)); 1658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r18); 1659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeft_(r6, r18, r6); 1660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(r6, r11, r6); 1661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 2 (r4): Previous index. 1663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Already there 1664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Argument 1 (r3): Subject string. 1666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r3, subject); 1667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Locate the code entry and call it. 1669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(code, code, Operand(Code::kHeaderSize - kHeapObjectTag)); 1670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DirectCEntryStub stub(isolate()); 1672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub.GenerateCall(masm, code); 1673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LeaveExitFrame(false, no_reg, true); 1675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r3: result (int32) 1677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // subject: subject string (callee saved) 1678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // regexp_data: RegExp data (callee saved) 1679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // last_match_info_elements: Last match info elements (callee saved) 1680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check the result. 1681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label success; 1682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpwi(r3, Operand(1)); 1683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We expect exactly one result since we force the called regexp to behave 1684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // as non-global. 1685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&success); 1686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label failure; 1687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpwi(r3, Operand(NativeRegExpMacroAssembler::FAILURE)); 1688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&failure); 1689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpwi(r3, Operand(NativeRegExpMacroAssembler::EXCEPTION)); 1690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If not exception it can only be retry. Handle that in the runtime system. 1691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&runtime); 1692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Result must now be exception. If there is no pending exception already a 1693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stack overflow (on the backtrack stack) was detected in RegExp code but 1694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // haven't created the exception yet. Handle that in the runtime system. 1695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // TODO(592): Rerunning the RegExp to get the stack overflow exception. 1696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r4, Operand(isolate()->factory()->the_hole_value())); 1697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r5, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate()))); 1699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, MemOperand(r5, 0)); 1700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r3, r4); 1701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&runtime); 1702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // For exception, throw the exception again. 1704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kRegExpExecReThrow); 1705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&failure); 1707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For failure and exception return null. 1708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(isolate()->factory()->null_value())); 1709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(sp, sp, Operand(4 * kPointerSize)); 1710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 1711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Process the result from the native regexp code. 1713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&success); 1714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r4, 1715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 1716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Calculate number of capture registers (number_of_captures + 1) * 2. 1717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // SmiToShortArrayOffset accomplishes the multiplication by 2 and 1718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // SmiUntag (which is a nop for 32-bit). 1719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToShortArrayOffset(r4, r4); 1720958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r4, r4, Operand(2)); 1721958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, MemOperand(sp, kLastMatchInfoOffset)); 1723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r3, &runtime); 1724958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(r3, r5, r5, JS_ARRAY_TYPE); 1725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&runtime); 1726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the JSArray is in fast case. 1727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(last_match_info_elements, 1728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(r3, JSArray::kElementsOffset)); 1729958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, 1730958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); 1731958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareRoot(r3, Heap::kFixedArrayMapRootIndex); 1732958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&runtime); 1733958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the last match info has space for the capture registers and the 1734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // additional information. 1735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP( 1736958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r3, FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); 1737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r5, r4, Operand(RegExpImpl::kLastMatchOverhead)); 1738958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r0, r3); 1739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r5, r0); 1740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bgt(&runtime); 1741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: number of capture registers 1743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // subject: subject string 1744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Store the capture count. 1745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiTag(r5, r4); 1746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r5, FieldMemOperand(last_match_info_elements, 1747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier RegExpImpl::kLastCaptureCountOffset), 1748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r0); 1749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Store last subject and last input. 1750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(subject, FieldMemOperand(last_match_info_elements, 1751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier RegExpImpl::kLastSubjectOffset), 1752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r0); 1753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r5, subject); 1754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ RecordWriteField(last_match_info_elements, RegExpImpl::kLastSubjectOffset, 1755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier subject, r10, kLRHasNotBeenSaved, kDontSaveFPRegs); 1756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(subject, r5); 1757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(subject, FieldMemOperand(last_match_info_elements, 1758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier RegExpImpl::kLastInputOffset), 1759958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r0); 1760958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ RecordWriteField(last_match_info_elements, RegExpImpl::kLastInputOffset, 1761958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier subject, r10, kLRHasNotBeenSaved, kDontSaveFPRegs); 1762958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1763958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get the static offsets vector filled by the native regexp code. 1764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference address_of_static_offsets_vector = 1765958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::address_of_static_offsets_vector(isolate()); 1766958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r5, Operand(address_of_static_offsets_vector)); 1767958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: number of capture registers 1769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: offsets vector 1770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label next_capture; 1771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Capture register counter starts from number of capture registers and 1772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // counts down until wraping after zero. 1773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi( 1774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r3, last_match_info_elements, 1775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag - kPointerSize)); 1776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r5, r5, Operand(-kIntSize)); // bias down for lwzu 1777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtctr(r4); 1778958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&next_capture); 1779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Read the value from the static offsets vector buffer. 1780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwzu(r6, MemOperand(r5, kIntSize)); 1781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Store the smi value in the last match info. 1782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiTag(r6); 1783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StorePU(r6, MemOperand(r3, kPointerSize)); 1784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bdnz(&next_capture); 1785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return last match info. 1787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, MemOperand(sp, kLastMatchInfoOffset)); 1788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(sp, sp, Operand(4 * kPointerSize)); 1789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 1790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Do the runtime call to execute the regexp. 1792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&runtime); 1793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kRegExpExec); 1794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Deferred code for string handling. 1796109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (5) Long external string? If not, go to (7). 1797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_seq_nor_cons); 1798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare flags are still set. 1799109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bgt(¬_long_external); // Go to (7). 1800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1801109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (6) External string. Make it, offset-wise, look like a sequential string. 1802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&external_string); 1803958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset)); 1804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset)); 1805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (FLAG_debug_code) { 1806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Assert that we do not have a cons or slice (indirect strings) here. 1807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Sequential strings have already been ruled out. 1808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kIsIndirectStringMask == 1); 1809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r3, Operand(kIsIndirectStringMask)); 1810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Assert(eq, kExternalStringExpectedButNotFound, cr0); 1811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(subject, 1813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(subject, ExternalString::kResourceDataOffset)); 1814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Move the pointer so that offset-wise, it looks like a sequential string. 1815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 1816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subi(subject, subject, 1817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 1818109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&seq_string); // Go to (4). 1819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1820109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (7) Short external string or not a string? If yes, bail out to runtime. 1821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_long_external); 1822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag != 0); 1823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r4, Operand(kIsNotStringMask | kShortExternalStringMask)); 1824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&runtime, cr0); 1825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (8) Sliced string. Replace subject with parent. Go to (4). 1827958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load offset into r11 and replace subject string with parent. 1828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset)); 1829958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r11); 1830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); 1831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&check_underlying); // Go to (4). 1832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif // V8_INTERPRETED_REGEXP 1833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { 1837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r3 : number of arguments to the construct function 1838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r4 : the function to call 1839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r5 : feedback vector 1840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r6 : slot in feedback vector (Smi) 1841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 1842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Number-of-arguments register must be smi-tagged to call out. 1844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiTag(r3); 1845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(r6, r5, r4, r3); 1846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallStub(stub); 1848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(r6, r5, r4, r3); 1850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(r3); 1851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1854958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void GenerateRecordCallTarget(MacroAssembler* masm) { 1855958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Cache the called function in a feedback vector slot. Cache states 1856958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // are uninitialized, monomorphic (indicated by a JSFunction), and 1857958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // megamorphic. 1858958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3 : number of arguments to the construct function 1859958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4 : the function to call 1860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r5 : feedback vector 1861958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6 : slot in feedback vector (Smi) 1862958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label initialize, done, miss, megamorphic, not_array_function; 1863958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1864958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()), 1865958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm->isolate()->heap()->megamorphic_symbol()); 1866958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()), 1867958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm->isolate()->heap()->uninitialized_symbol()); 1868958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the cache state into r8. 1870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiToPtrArrayOffset(r8, r6); 1871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(r8, r5, r8); 1872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r8, FieldMemOperand(r8, FixedArray::kHeaderSize)); 1873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1874958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // A monomorphic cache hit or an already megamorphic state: invoke the 1875958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // function without changing the state. 1876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We don't know if r8 is a WeakCell or a Symbol, but it's harmless to read at 1877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // this position in a symbol (see static asserts in type-feedback-vector.h). 1878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label check_allocation_site; 1879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register feedback_map = r9; 1880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register weak_value = r10; 1881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(weak_value, FieldMemOperand(r8, WeakCell::kValueOffset)); 1882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, weak_value); 1883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&done); 1884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r8, Heap::kmegamorphic_symbolRootIndex); 1885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&done); 1886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(feedback_map, FieldMemOperand(r8, HeapObject::kMapOffset)); 1887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex); 1888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&check_allocation_site); 1889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the weak cell is cleared, we have a new chance to become monomorphic. 1891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(weak_value, &initialize); 1892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&megamorphic); 1893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&check_allocation_site); 1895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If we came here, we need to see if we are the array function. 1896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If we didn't have a matching function, and we didn't find the megamorph 1897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // sentinel, then we have in the slot either some other function or an 1898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // AllocationSite. 1899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(feedback_map, Heap::kAllocationSiteMapRootIndex); 1900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&miss); 1901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make sure the function is the Array() function 1903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8); 1904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, r8); 1905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&megamorphic); 1906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&done); 1907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1908958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 1909958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1910958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // A monomorphic miss (i.e, here the cache is not uninitialized) goes 1911958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // megamorphic. 1912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r8, Heap::kuninitialized_symbolRootIndex); 1913958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&initialize); 1914958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // MegamorphicSentinel is an immortal immovable object (undefined) so no 1915958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // write-barrier is needed. 1916958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&megamorphic); 1917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiToPtrArrayOffset(r8, r6); 1918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(r8, r5, r8); 1919958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); 1920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(ip, FieldMemOperand(r8, FixedArray::kHeaderSize), r0); 1921958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ jmp(&done); 1922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1923958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // An uninitialized cache is patched with the function 1924958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&initialize); 1925958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make sure the function is the Array() function. 1927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8); 1928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, r8); 1929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(¬_array_function); 1930958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The target function is the Array constructor, 1932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Create an AllocationSite if we don't already have it, store it in the 1933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // slot. 1934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CreateAllocationSiteStub create_stub(masm->isolate()); 1935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallStubInRecordCallTarget(masm, &create_stub); 1936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&done); 1937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(¬_array_function); 1939958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CreateWeakCellStub weak_cell_stub(masm->isolate()); 1941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallStubInRecordCallTarget(masm, &weak_cell_stub); 1942958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&done); 1943958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1944958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1945958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CallConstructStub::Generate(MacroAssembler* masm) { 1947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r3 : number of arguments 1948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r4 : the function to call 1949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r5 : feedback vector 1950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r6 : slot in feedback vector (Smi, for RecordCallTarget) 1951958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label non_function; 1953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check that the function is not a smi. 1954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(r4, &non_function); 1955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check that the function is a JSFunction. 1956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r4, r8, r8, JS_FUNCTION_TYPE); 1957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&non_function); 1958958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateRecordCallTarget(masm); 1960958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiToPtrArrayOffset(r8, r6); 1962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(r8, r5, r8); 1963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Put the AllocationSite from the feedback vector into r5, or undefined. 1964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize)); 1965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r8, FieldMemOperand(r5, AllocationSite::kMapOffset)); 1966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex); 1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 1968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); 1969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, r5, r5, r8); 1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label feedback_register_initialized; 1972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&feedback_register_initialized); 1973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); 1974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&feedback_register_initialized); 1975958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1976958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertUndefinedOrAllocationSite(r5, r8); 1978958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Pass function as new target. 1980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r6, r4); 1981958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Tail call to the function-specific construct stub (still in the caller 1983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // context at this point). 1984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 1985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r7, FieldMemOperand(r7, SharedFunctionInfo::kConstructStubOffset)); 1986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addi(ip, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); 1987958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpToJSEntry(ip); 1988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&non_function); 1990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r6, r4); 1991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 1992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1993958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { 1996958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4 - function 1997958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6 - slot id 1998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r5 - vector 1999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r7 - allocation site (loaded from vector[slot]) 2000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8); 2001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, r8); 2002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(miss); 2003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(arg_count())); 2005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Increment the call count for monomorphic function calls. 2007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int count_offset = FixedArray::kHeaderSize + kPointerSize; 2008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiToPtrArrayOffset(r8, r6); 2009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(r5, r5, r8); 2010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r6, FieldMemOperand(r5, count_offset)); 2011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AddSmiLiteral(r6, r6, Smi::FromInt(CallICNexus::kCallCountIncrement), r0); 2012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(r6, FieldMemOperand(r5, count_offset), r0); 2013958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2014958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r5, r7); 2015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r6, r4); 2016958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ArrayConstructorStub stub(masm->isolate(), arg_count()); 2017958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallStub(&stub); 2018958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2019958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2020958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2021958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CallICStub::Generate(MacroAssembler* masm) { 2022958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4 - function 2023958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6 - slot id (Smi) 2024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r5 - vector 2025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label extra_checks_or_miss, call, call_function; 2026958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int argc = arg_count(); 2027958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ParameterCount actual(argc); 2028958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2029958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The checks. First, does r4 match the recorded monomorphic target? 2030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiToPtrArrayOffset(r9, r6); 2031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(r9, r5, r9); 2032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r7, FieldMemOperand(r9, FixedArray::kHeaderSize)); 2033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We don't know that we have a weak cell. We might have a private symbol 2035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // or an AllocationSite, but the memory is safe to examine. 2036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to 2037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // FixedArray. 2038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // WeakCell::kValueOffset - contains a JSFunction or Smi(0) 2039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not 2040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // computed, meaning that it can't appear to be a pointer. If the low bit is 2041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 0, then hash is computed, but the 0 bit prevents the field from appearing 2042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // to be a pointer. 2043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(WeakCell::kSize >= kPointerSize); 2044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == 2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch WeakCell::kValueOffset && 2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch WeakCell::kValueOffset == Symbol::kHashFieldSlot); 2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r8, FieldMemOperand(r7, WeakCell::kValueOffset)); 2049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, r8); 2050958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&extra_checks_or_miss); 2051958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The compare above could have been a SMI/SMI comparison. Guard against this 2053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // convincing us that we have a monomorphic JSFunction. 2054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(r4, &extra_checks_or_miss); 2055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Increment the call count for monomorphic function calls. 2057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int count_offset = FixedArray::kHeaderSize + kPointerSize; 2058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r6, FieldMemOperand(r9, count_offset)); 2059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AddSmiLiteral(r6, r6, Smi::FromInt(CallICNexus::kCallCountIncrement), r0); 2060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(r6, FieldMemOperand(r9, count_offset), r0); 2061958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&call_function); 2063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r3, Operand(argc)); 2064109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), 2065109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch tail_call_mode()), 2066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2067958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&extra_checks_or_miss); 2069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label uninitialized, miss, not_allocation_site; 2070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r7, Heap::kmegamorphic_symbolRootIndex); 2072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&call); 2073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Verify that r7 contains an AllocationSite 2075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r8, FieldMemOperand(r7, HeapObject::kMapOffset)); 2076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex); 2077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(¬_allocation_site); 2078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We have an allocation site. 2080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HandleArrayCase(masm, &miss); 2081958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(¬_allocation_site); 2083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The following cases attempt to handle MISS cases without going to the 2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // runtime. 2086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_trace_ic) { 2087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&miss); 2088958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r7, Heap::kuninitialized_symbolRootIndex); 2091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&uninitialized); 2092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We are going megamorphic. If the feedback is a JSFunction, it is fine 2094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // to handle it here. More complex cases are dealt with in the runtime. 2095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertNotSmi(r7); 2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r7, r8, r8, JS_FUNCTION_TYPE); 2097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&miss); 2098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); 2099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(ip, FieldMemOperand(r9, FixedArray::kHeaderSize), r0); 2100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&call); 2102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r3, Operand(argc)); 2103109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), 2104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&uninitialized); 2107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We are going monomorphic, provided we actually have a JSFunction. 2109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(r4, &miss); 2110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Goto miss case if we do not have a function. 2112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE); 2113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&miss); 2114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make sure the function is not the Array() function, which requires special 2116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // behavior on MISS. 2117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r7); 2118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, r7); 2119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&miss); 2120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make sure the function belongs to the same native context. 2122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r7, FieldMemOperand(r4, JSFunction::kContextOffset)); 2123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r7, ContextMemOperand(r7, Context::NATIVE_CONTEXT_INDEX)); 2124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(ip, NativeContextMemOperand()); 2125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r7, ip); 2126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&miss); 2127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Initialize the call counter. 2129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r8, Smi::FromInt(CallICNexus::kCallCountIncrement)); 2130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(r8, FieldMemOperand(r9, count_offset), r0); 2131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Store the function. Use a stub since we need a frame for allocation. 2133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r5 - vector 2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r6 - slot 2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r4 - function 2136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 2137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CreateWeakCellStub create_stub(masm->isolate()); 2139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(r4); 2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallStub(&create_stub); 2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(r4); 2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&call_function); 2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We are here because tracing is on or we encountered a MISS case we can't 2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // handle here. 2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&miss); 2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateMiss(masm); 2150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&call); 2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CallICStub::GenerateMiss(MacroAssembler* masm) { 2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 2157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push the function and feedback info. 2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(r4, r5, r6); 2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the entry. 2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCallIC_Miss); 2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Move result to r4 and exit the internal frame. 2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r4, r3); 2166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// StringCharCodeAtGenerator 2170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 2171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If the receiver is a smi trigger the non-string case. 2172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (check_mode_ == RECEIVER_IS_UNKNOWN) { 2173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(object_, receiver_not_string_); 2174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Fetch the instance type of the receiver into result register. 2176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 2177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 2178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If the receiver is not a string trigger the non-string case. 2179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, result_, Operand(kIsNotStringMask)); 2180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(receiver_not_string_, cr0); 2181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If the index is non-smi trigger the non-smi case. 2184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(index_, &index_not_smi_); 2185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&got_smi_index_); 2186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for index out of range. 2188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(ip, FieldMemOperand(object_, String::kLengthOffset)); 2189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpl(ip, index_); 2190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ble(index_out_of_range_); 2191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(index_); 2193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringCharLoadGenerator::Generate(masm, object_, index_, result_, 2195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &call_runtime_); 2196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiTag(result_); 2198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&exit_); 2199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringCharCodeAtGenerator::GenerateSlow( 2203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm, EmbedMode embed_mode, 2204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const RuntimeCallHelper& call_helper) { 2205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase); 2206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Index is not a smi. 2208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&index_not_smi_); 2209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If index is a heap number, try converting it to an integer. 2210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckMap(index_, result_, Heap::kHeapNumberMapRootIndex, index_not_number_, 2211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DONT_DO_SMI_CHECK); 2212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_helper.BeforeCall(masm); 2213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (embed_mode == PART_OF_IC_HANDLER) { 2214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(LoadWithVectorDescriptor::VectorRegister(), 2215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadWithVectorDescriptor::SlotRegister(), object_, index_); 2216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // index_ is consumed by runtime conversion function. 2218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(object_, index_); 2219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (index_flags_ == STRING_INDEX_IS_NUMBER) { 2221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero); 2222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 2224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // NumberToSmi discards numbers that are not exact integers. 2225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNumberToSmi); 2226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Save the conversion result before the pop instructions below 2228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // have a chance to overwrite it. 2229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(index_, r3); 2230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (embed_mode == PART_OF_IC_HANDLER) { 2231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(LoadWithVectorDescriptor::VectorRegister(), 2232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadWithVectorDescriptor::SlotRegister(), object_); 2233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(object_); 2235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Reload the instance type. 2237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 2238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 2239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_helper.AfterCall(masm); 2240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If index is still not a smi, it must be out of range. 2241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(index_, index_out_of_range_); 2242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Otherwise, return to the fast path. 2243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&got_smi_index_); 2244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call runtime. We get here when the receiver is a string and the 2246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // index is a number, but the code of getting the actual character 2247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // is too complex (e.g., when the string needs to be flattened). 2248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&call_runtime_); 2249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_helper.BeforeCall(masm); 2250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiTag(index_); 2251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(object_, index_); 2252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kStringCharCodeAtRT); 2253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(result_, r3); 2254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_helper.AfterCall(masm); 2255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&exit_); 2256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); 2258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// ------------------------------------------------------------------------- 2262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// StringCharFromCodeGenerator 2263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 2265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Fast case of Heap::LookupSingleCharacterStringFromCode. 2266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCodeU + 1)); 2267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r0, Smi::FromInt(~String::kMaxOneByteCharCodeU)); 2268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ori(r0, r0, Operand(kSmiTagMask)); 2269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ and_(r0, code_, r0, SetRC); 2270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&slow_case_, cr0); 2271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); 2273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // At this point code register contains smi tagged one-byte char code. 2274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r0, code_); 2275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToPtrArrayOffset(code_, code_); 2276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(result_, result_, code_); 2277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(code_, r0); 2278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); 2279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareRoot(result_, Heap::kUndefinedValueRootIndex); 2280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&slow_case_); 2281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&exit_); 2282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringCharFromCodeGenerator::GenerateSlow( 2286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, const RuntimeCallHelper& call_helper) { 2287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); 2288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&slow_case_); 2290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_helper.BeforeCall(masm); 2291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(code_); 2292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kStringCharFromCode); 2293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(result_, r3); 2294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_helper.AfterCall(masm); 2295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&exit_); 2296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 2298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierenum CopyCharactersFlags { COPY_ONE_BYTE = 1, DEST_ALWAYS_ALIGNED = 2 }; 2302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringHelper::GenerateCopyCharacters(MacroAssembler* masm, Register dest, 2305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register src, Register count, 2306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch, 2307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier String::Encoding encoding) { 2308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (FLAG_debug_code) { 2309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that destination is word aligned. 2310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, dest, Operand(kPointerAlignmentMask)); 2311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Check(eq, kDestinationOfCopyNotAligned, cr0); 2312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Nothing to do for zero characters. 2315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label done; 2316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (encoding == String::TWO_BYTE_ENCODING) { 2317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // double the length 2318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(count, count, count, LeaveOE, SetRC); 2319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&done, cr0); 2320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(count, Operand::Zero()); 2322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&done); 2323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Copy count bytes from src to dst. 2326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label byte_loop; 2327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtctr(count); 2328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&byte_loop); 2329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(scratch, MemOperand(src)); 2330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(src, src, Operand(1)); 2331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ stb(scratch, MemOperand(dest)); 2332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(dest, dest, Operand(1)); 2333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bdnz(&byte_loop); 2334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&done); 2336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid SubStringStub::Generate(MacroAssembler* masm) { 2340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label runtime; 2341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stack frame on entry. 2343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // lr: return address 2344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // sp[0]: to 2345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // sp[4]: from 2346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // sp[8]: string 2347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // This stub is called from the native-call %_SubString(...), so 2349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // nothing can be assumed about the arguments. It is tested that: 2350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // "string" is a sequential string, 2351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // both "from" and "to" are smis, and 2352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 0 <= from <= to <= string.length. 2353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If any of these assumptions fail, we call the runtime system. 2354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int kToOffset = 0 * kPointerSize; 2356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int kFromOffset = 1 * kPointerSize; 2357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int kStringOffset = 2 * kPointerSize; 2358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r5, MemOperand(sp, kToOffset)); 2360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r6, MemOperand(sp, kFromOffset)); 2361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If either to or from had the smi tag bit set, then fail to generic runtime 2363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r5, &runtime); 2364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r6, &runtime); 2365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r5); 2366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r6, SetRC); 2367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Both r5 and r6 are untagged integers. 2368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We want to bailout to runtime here if From is negative. 2370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(&runtime, cr0); // From < 0. 2371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpl(r6, r5); 2373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bgt(&runtime); // Fail if from > to. 2374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ sub(r5, r5, r6); 2375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure first argument is a string. 2377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, MemOperand(sp, kStringOffset)); 2378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r3, &runtime); 2379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Condition is_string = masm->IsObjectStringType(r3, r4); 2380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(NegateCondition(is_string), &runtime, cr0); 2381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label single_char; 2383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r5, Operand(1)); 2384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(eq, &single_char); 2385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Short-cut for the case of trivial substring. 2387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label return_r3; 2388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: original string 2389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: result string length 2390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r7, FieldMemOperand(r3, String::kLengthOffset)); 2391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r0, r7); 2392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpl(r5, r0); 2393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return original string. 2394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&return_r3); 2395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Longer than original string's length or negative: unsafe arguments. 2396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bgt(&runtime); 2397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Shorter than original string's length: an actual substring. 2398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Deal with different string types: update the index if necessary 2400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // and put the underlying string into r8. 2401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: original string 2402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: instance type 2403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: length 2404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: from index (untagged) 2405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label underlying_unpacked, sliced_string, seq_or_external_string; 2406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If the string is not indirect, it can only be sequential or external. 2407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); 2408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kIsIndirectStringMask != 0); 2409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r4, Operand(kIsIndirectStringMask)); 2410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&seq_or_external_string, cr0); 2411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r4, Operand(kSlicedNotConsMask)); 2413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&sliced_string, cr0); 2414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Cons string. Check whether it is flat, then fetch first part. 2415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r8, FieldMemOperand(r3, ConsString::kSecondOffset)); 2416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareRoot(r8, Heap::kempty_stringRootIndex); 2417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&runtime); 2418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r8, FieldMemOperand(r3, ConsString::kFirstOffset)); 2419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Update instance type. 2420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r4, FieldMemOperand(r8, HeapObject::kMapOffset)); 2421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 2422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&underlying_unpacked); 2423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&sliced_string); 2425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Sliced string. Fetch parent and correct start index by offset. 2426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r8, FieldMemOperand(r3, SlicedString::kParentOffset)); 2427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r7, FieldMemOperand(r3, SlicedString::kOffsetOffset)); 2428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r4, r7); 2429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(r6, r6, r4); // Add offset to index. 2430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Update instance type. 2431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r4, FieldMemOperand(r8, HeapObject::kMapOffset)); 2432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 2433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&underlying_unpacked); 2434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&seq_or_external_string); 2436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Sequential or external string. Just move string to the expected register. 2437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r8, r3); 2438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&underlying_unpacked); 2440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (FLAG_string_slices) { 2442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label copy_routine; 2443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r8: underlying subject string 2444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: instance type of underlying subject string 2445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: length 2446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: adjusted start index (untagged) 2447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r5, Operand(SlicedString::kMinLength)); 2448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Short slice. Copy instead of slicing. 2449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(©_routine); 2450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Allocate new sliced string. At this point we do not reload the instance 2451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // type including the string encoding because we simply rely on the info 2452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // provided by the original string. It does not matter if the original 2453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // string's encoding is wrong because we always have to recheck encoding of 2454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the newly created string's parent anyways due to externalized strings. 2455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label two_byte_slice, set_slice_header; 2456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); 2457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 2458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r4, Operand(kStringEncodingMask)); 2459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&two_byte_slice, cr0); 2460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ AllocateOneByteSlicedString(r3, r5, r9, r10, &runtime); 2461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&set_slice_header); 2462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&two_byte_slice); 2463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ AllocateTwoByteSlicedString(r3, r5, r9, r10, &runtime); 2464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&set_slice_header); 2465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiTag(r6); 2466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r8, FieldMemOperand(r3, SlicedString::kParentOffset), r0); 2467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r6, FieldMemOperand(r3, SlicedString::kOffsetOffset), r0); 2468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&return_r3); 2469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(©_routine); 2471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r8: underlying subject string 2474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: instance type of underlying subject string 2475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: length 2476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: adjusted start index (untagged) 2477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label two_byte_sequential, sequential_string, allocate_result; 2478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kExternalStringTag != 0); 2479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSeqStringTag == 0); 2480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r4, Operand(kExternalStringTag)); 2481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&sequential_string, cr0); 2482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Handle external string. 2484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Rule out short external strings. 2485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kShortExternalStringTag != 0); 2486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r4, Operand(kShortExternalStringTag)); 2487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&runtime, cr0); 2488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r8, FieldMemOperand(r8, ExternalString::kResourceDataOffset)); 2489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r8 already points to the first character of underlying string. 2490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&allocate_result); 2491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&sequential_string); 2493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Locate first character of underlying subject string. 2494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 2495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r8, r8, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 2496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&allocate_result); 2498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Sequential acii string. Allocate the result. 2499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); 2500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, r4, Operand(kStringEncodingMask)); 2501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&two_byte_sequential, cr0); 2502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Allocate and copy the resulting one-byte string. 2504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ AllocateOneByteString(r3, r5, r7, r9, r10, &runtime); 2505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Locate first character of substring to copy. 2507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(r8, r8, r6); 2508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Locate first character of result. 2509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r4, r3, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 2510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: result string 2512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: first character of result string 2513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: result string length 2514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r8: first character of substring to copy 2515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); 2516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringHelper::GenerateCopyCharacters(masm, r4, r8, r5, r6, 2517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier String::ONE_BYTE_ENCODING); 2518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&return_r3); 2519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Allocate and copy the resulting two-byte string. 2521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&two_byte_sequential); 2522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ AllocateTwoByteString(r3, r5, r7, r9, r10, &runtime); 2523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Locate first character of substring to copy. 2525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeftImm(r4, r6, Operand(1)); 2526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(r8, r8, r4); 2527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Locate first character of result. 2528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r4, r3, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 2529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: result string. 2531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: first character of result. 2532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: result length. 2533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r8: first character of substring to copy. 2534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 2535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringHelper::GenerateCopyCharacters(masm, r4, r8, r5, r6, 2536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier String::TWO_BYTE_ENCODING); 2537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&return_r3); 2539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Counters* counters = isolate()->counters(); 2540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(counters->sub_string_native(), 1, r6, r7); 2541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Drop(3); 2542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Just jump to runtime to create the sub string. 2545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&runtime); 2546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kSubString); 2547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&single_char); 2549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3: original string 2550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: instance type 2551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r5: length 2552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r6: from index (untagged) 2553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiTag(r6, r6); 2554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringCharAtGenerator generator(r3, r6, r5, r3, &runtime, &runtime, &runtime, 2555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING); 2556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier generator.GenerateFast(masm); 2557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Drop(3); 2558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier generator.SkipSlow(masm, &runtime); 2560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid ToNumberStub::Generate(MacroAssembler* masm) { 2564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The ToNumber stub takes one argument in r3. 25653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 25663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ TestIfSmi(r3, r0); 25673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Ret(eq, cr0); 2568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r3, r4, r4, HEAP_NUMBER_TYPE); 2570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r3: receiver 2571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r4: receiver instance type 2572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(eq); 2573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 25743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch NonNumberToNumberStub stub(masm->isolate()); 25753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ TailCallStub(&stub); 25763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 25773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 25783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid NonNumberToNumberStub::Generate(MacroAssembler* masm) { 25793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // The NonNumberToNumber stub takes one argument in r3. 25803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ AssertNotNumber(r3); 25813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 25823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CompareObjectType(r3, r4, r4, FIRST_NONSTRING_TYPE); 25833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // r3: receiver 25843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // r4: receiver instance type 25853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch StringToNumberStub stub(masm->isolate()); 25863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ TailCallStub(&stub, lt); 2587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label not_oddball; 2589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(r4, Operand(ODDBALL_TYPE)); 2590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(¬_oddball); 2591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset)); 2592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blr(); 2593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(¬_oddball); 2594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(r3); // Push argument. 2596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kToNumber); 2597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 25993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid StringToNumberStub::Generate(MacroAssembler* masm) { 26003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // The StringToNumber stub takes one argument in r3. 26013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ AssertString(r3); 2602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 26033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Check if string has a cached array index. 26043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label runtime; 26053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ lwz(r5, FieldMemOperand(r3, String::kHashFieldOffset)); 26063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ And(r0, r5, Operand(String::kContainsCachedArrayIndexMask), SetRC); 26073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bne(&runtime, cr0); 26083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ IndexFromHash(r5, r3); 26093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ blr(); 2610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 26113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bind(&runtime); 2612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(r3); // Push argument. 26133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ TailCallRuntime(Runtime::kStringToNumber); 2614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid ToStringStub::Generate(MacroAssembler* masm) { 2617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The ToString stub takes one argument in r3. 2618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label is_number; 2619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(r3, &is_number); 2620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r3, r4, r4, FIRST_NONSTRING_TYPE); 2622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r3: receiver 2623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r4: receiver instance type 2624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(lt); 2625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label not_heap_number; 2627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(r4, Operand(HEAP_NUMBER_TYPE)); 2628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(¬_heap_number); 2629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&is_number); 2630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch NumberToStringStub stub(isolate()); 2631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallStub(&stub); 2632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(¬_heap_number); 2633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label not_oddball; 2635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(r4, Operand(ODDBALL_TYPE)); 2636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(¬_oddball); 2637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r3, FieldMemOperand(r3, Oddball::kToStringOffset)); 2638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(¬_oddball); 2640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(r3); // Push argument. 2642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kToString); 2643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2646109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ToNameStub::Generate(MacroAssembler* masm) { 2647109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The ToName stub takes one argument in r3. 2648109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label is_number; 2649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(r3, &is_number); 2650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2651109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); 2652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareObjectType(r3, r4, r4, LAST_NAME_TYPE); 2653109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r3: receiver 2654109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r4: receiver instance type 2655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(le); 2656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2657109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label not_heap_number; 2658109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r4, Operand(HEAP_NUMBER_TYPE)); 2659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(¬_heap_number); 2660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&is_number); 2661109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch NumberToStringStub stub(isolate()); 2662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub); 2663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(¬_heap_number); 2664109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2665109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label not_oddball; 2666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r4, Operand(ODDBALL_TYPE)); 2667109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(¬_oddball); 2668109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, FieldMemOperand(r3, Oddball::kToStringOffset)); 2669109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 2670109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(¬_oddball); 2671109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2672109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ push(r3); // Push argument. 2673109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallRuntime(Runtime::kToName); 2674109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2675109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2676109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, 2678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register left, 2679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register right, 2680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch1, 2681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch2) { 2682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register length = scratch1; 2683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare lengths. 2685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label strings_not_equal, check_zero_length; 2686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(length, FieldMemOperand(left, String::kLengthOffset)); 2687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset)); 2688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(length, scratch2); 2689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&check_zero_length); 2690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&strings_not_equal); 2691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(NOT_EQUAL)); 2692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if the length is zero. 2695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label compare_chars; 2696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&check_zero_length); 2697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 2698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(length, Operand::Zero()); 2699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&compare_chars); 2700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 2701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare characters. 2704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&compare_chars); 2705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, 2706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &strings_not_equal); 2707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Characters are equal. 2709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 2710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringHelper::GenerateCompareFlatOneByteStrings( 2715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Register left, Register right, Register scratch1, 2716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch2, Register scratch3) { 2717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label result_not_equal, compare_lengths; 2718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Find minimum length and length difference. 2719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch1, FieldMemOperand(left, String::kLengthOffset)); 2720958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset)); 2721958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ sub(scratch3, scratch1, scratch2, LeaveOE, SetRC); 2722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register length_delta = scratch3; 2723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 2724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(gt, scratch1, scratch2, scratch1, cr0); 2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label skip; 2727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ble(&skip, cr0); 2728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(scratch1, scratch2); 2729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&skip); 2730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2731958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register min_length = scratch1; 2732958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 2733958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(min_length, Operand::Zero()); 2734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&compare_lengths); 2735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2736958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare loop. 2737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2, 2738958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &result_not_equal); 2739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare lengths - strings up to min-length are equal. 2741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&compare_lengths); 2742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); 2743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Use length_delta as result if it's zero. 2744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r3, length_delta); 2745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r3, Operand::Zero()); 2746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&result_not_equal); 2747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Conditionally update the result based either on length_delta or 2748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the last comparion performed in the loop above. 2749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 2750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r4, Smi::FromInt(GREATER)); 2751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r5, Smi::FromInt(LESS)); 2752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, r3, r0, r4); 2753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(lt, r3, r5, r3); 2754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2756014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label less_equal, equal; 2757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ble(&less_equal); 2758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r3, Smi::FromInt(GREATER)); 2759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&less_equal); 2761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&equal); 2762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r3, Smi::FromInt(LESS)); 2763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&equal); 2764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2766958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2767958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringHelper::GenerateOneByteCharsCompareLoop( 2770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Register left, Register right, Register length, 2771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch1, Label* chars_not_equal) { 2772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Change index to run from -length to -1 by adding length to string 2773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // start. This means that loop ends when index reaches zero, which 2774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // doesn't need an additional compare. 2775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(length); 2776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(scratch1, length, 2777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 2778958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(left, left, scratch1); 2779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(right, right, scratch1); 2780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subfic(length, length, Operand::Zero()); 2781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register index = length; // index = -length; 2782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare loop. 2784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label loop; 2785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&loop); 2786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbzx(scratch1, MemOperand(left, index)); 2787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbzx(r0, MemOperand(right, index)); 2788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(scratch1, r0); 2789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(chars_not_equal); 2790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(index, index, Operand(1)); 2791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(index, Operand::Zero()); 2792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&loop); 2793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { 2797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------- S t a t e ------------- 2798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r4 : left 2799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r3 : right 2800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- lr : return address 2801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------------------------------- 2802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2803958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load r5 with the allocation site. We stick an undefined dummy value here 2804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // and replace it with the real allocation site later when we instantiate this 2805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate(). 2806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(r5, handle(isolate()->heap()->undefined_value())); 2807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure that we actually patched the allocation site. 2809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (FLAG_debug_code) { 2810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TestIfSmi(r5, r0); 2811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Assert(ne, kExpectedAllocationSite, cr0); 2812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r5); 2813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r5, FieldMemOperand(r5, HeapObject::kMapOffset)); 2814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(ip, Heap::kAllocationSiteMapRootIndex); 2815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r5, ip); 2816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(r5); 2817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Assert(eq, kExpectedAllocationSite); 2818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2820958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Tail call into the stub that handles binary operations with allocation 2821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // sites. 2822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier BinaryOpWithAllocationSiteStub stub(isolate(), state()); 2823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallStub(&stub); 2824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CompareICStub::GenerateBooleans(MacroAssembler* masm) { 2828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(CompareICState::BOOLEAN, state()); 2829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label miss; 2830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CheckMap(r4, r5, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); 2832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CheckMap(r3, r6, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); 2833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!Token::IsEqualityOp(op())) { 2834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r4, FieldMemOperand(r4, Oddball::kToNumberOffset)); 2835109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertSmi(r4); 2836109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset)); 2837109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertSmi(r3); 2838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2839109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ sub(r3, r4, r3); 2840109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 2841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&miss); 2843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateMiss(masm); 2844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2847958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateSmis(MacroAssembler* masm) { 2848958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(state() == CompareICState::SMI); 2849958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 2850958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(r5, r4, r3); 2851958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r5, &miss); 2852958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2853958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (GetCondition() == eq) { 2854958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For equality we do not care about the sign of the result. 2855958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // __ sub(r3, r3, r4, SetCC); 2856958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ sub(r3, r3, r4); 2857958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2858958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Untag before subtracting to avoid handling overflow. 2859958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r4); 2860958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(r3); 2861958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ sub(r3, r4, r3); 2862958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2863958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2864958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2865958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 2866958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 2867958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2868958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2869958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2870958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateNumbers(MacroAssembler* masm) { 2871958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(state() == CompareICState::NUMBER); 2872958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label generic_stub; 2874958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label unordered, maybe_undefined1, maybe_undefined2; 2875958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 2876958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label equal, less_than; 2877958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2878958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (left() == CompareICState::SMI) { 2879958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r4, &miss); 2880958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2881958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (right() == CompareICState::SMI) { 2882958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(r3, &miss); 2883958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2884958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2885958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Inlining the double comparison and falling back to the general compare 2886958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stub if NaN is involved. 2887958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load left and right operand. 2888958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label done, left, left_smi, right_smi; 2889958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r3, &right_smi); 2890958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckMap(r3, r5, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, 2891958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DONT_DO_SMI_CHECK); 2892958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d1, FieldMemOperand(r3, HeapNumber::kValueOffset)); 2893958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&left); 2894958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&right_smi); 2895958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToDouble(d1, r3); 2896958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2897958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&left); 2898958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r4, &left_smi); 2899958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckMap(r4, r5, Heap::kHeapNumberMapRootIndex, &maybe_undefined2, 2900958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DONT_DO_SMI_CHECK); 2901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lfd(d0, FieldMemOperand(r4, HeapNumber::kValueOffset)); 2902958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&done); 2903958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&left_smi); 2904958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToDouble(d0, r4); 2905958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2906958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&done); 2907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2908958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare operands 2909958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ fcmpu(d0, d1); 2910958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2911958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Don't base result on status bits when a NaN is involved. 2912958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bunordered(&unordered); 2913958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2914958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return a result of -1, 0, or 1, based on status bits. 2915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 2916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(EQUAL == 0); 2917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r4, Operand(GREATER)); 2918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r5, Operand(LESS)); 2919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, r3, r0, r4); 2920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(lt, r3, r5, r3); 2921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&equal); 2924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blt(&less_than); 2925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // assume greater than 2926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(GREATER)); 2927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&equal); 2929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(EQUAL)); 2930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&less_than); 2932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(r3, Operand(LESS)); 2933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 2934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2935958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2936958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&unordered); 2937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&generic_stub); 2938109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CompareICStub stub(isolate(), op(), CompareICState::GENERIC, 2939958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompareICState::GENERIC, CompareICState::GENERIC); 2940958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 2941958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2942958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&maybe_undefined1); 2943958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (Token::IsOrderedRelationalCompareOp(op())) { 2944958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); 2945958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss); 2946958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r4, &unordered); 2947958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareObjectType(r4, r5, r5, HEAP_NUMBER_TYPE); 2948958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&maybe_undefined2); 2949958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&unordered); 2950958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2951958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2952958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&maybe_undefined2); 2953958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (Token::IsOrderedRelationalCompareOp(op())) { 2954958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareRoot(r4, Heap::kUndefinedValueRootIndex); 2955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&unordered); 2956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2958958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 2959958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 2960958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2961958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { 2964958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(state() == CompareICState::INTERNALIZED_STRING); 2965958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss, not_equal; 2966958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2967958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Registers containing left and right operands respectively. 2968958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register left = r4; 2969958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register right = r3; 2970958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp1 = r5; 2971958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp2 = r6; 2972958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2973958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are heap objects. 2974958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfEitherSmi(left, right, &miss); 2975958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2976958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are symbols. 2977958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 2978958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 2979958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 2980958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 2981958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 2982958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(tmp1, tmp1, tmp2); 2983958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 2984958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss, cr0); 2985958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2986958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Internalized strings are compared by identity. 2987958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(left, right); 2988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(¬_equal); 2989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure r3 is non-zero. At this point input operands are 2990958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // guaranteed to be non-zero. 2991958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(right.is(r3)); 2992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(EQUAL == 0); 2993958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 2994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 2995958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_equal); 2996958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 2997958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2998958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 2999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 3000958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3001958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { 3004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(state() == CompareICState::UNIQUE_NAME); 3005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(GetCondition() == eq); 3006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 3007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Registers containing left and right operands respectively. 3009958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register left = r4; 3010958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register right = r3; 3011958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp1 = r5; 3012958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp2 = r6; 3013958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3014958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are heap objects. 3015958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfEitherSmi(left, right, &miss); 3016958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3017958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are unique names. This leaves the instance 3018958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // types loaded in tmp1 and tmp2. 3019958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 3020958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 3021958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 3022958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 3023958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3024958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotUniqueNameInstanceType(tmp1, &miss); 3025958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotUniqueNameInstanceType(tmp2, &miss); 3026958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3027958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Unique names are compared by identity. 3028958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(left, right); 3029958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss); 3030958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure r3 is non-zero. At this point input operands are 3031958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // guaranteed to be non-zero. 3032958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(right.is(r3)); 3033958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(EQUAL == 0); 3034958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 3035958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 3036958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 3037958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3038958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 3039958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 3040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3041958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3042958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3043958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateStrings(MacroAssembler* masm) { 3044958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(state() == CompareICState::STRING); 3045958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss, not_identical, is_symbol; 3046958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3047958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool equality = Token::IsEqualityOp(op()); 3048958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3049958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Registers containing left and right operands respectively. 3050958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register left = r4; 3051958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register right = r3; 3052958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp1 = r5; 3053958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp2 = r6; 3054958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp3 = r7; 3055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp4 = r8; 3056958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3057958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are heap objects. 3058958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfEitherSmi(left, right, &miss); 3059958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3060958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both operands are strings. This leaves the instance 3061958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // types loaded in tmp1 and tmp2. 3062958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 3063958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 3064958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 3065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 3066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kNotStringTag != 0); 3067958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(tmp3, tmp1, tmp2); 3068958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, tmp3, Operand(kIsNotStringMask)); 3069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss, cr0); 3070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Fast check for identical strings. 3072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(left, right); 3073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(EQUAL == 0); 3074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kSmiTag == 0); 3075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(¬_identical); 3076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 3077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 3078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_identical); 3079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3080958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Handle not identical strings. 3081958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both strings are internalized strings. If they are, we're done 3083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // because we already know they are not identical. We know they are both 3084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // strings. 3085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (equality) { 3086958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(GetCondition() == eq); 3087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(kInternalizedTag == 0); 3088958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ orx(tmp3, tmp1, tmp2); 3089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, tmp3, Operand(kIsNotInternalizedMask)); 3090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure r3 is non-zero. At this point input operands are 3091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // guaranteed to be non-zero. 3092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(right.is(r3)); 3093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(eq, cr0); 3094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3095958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that both strings are sequential one-byte. 3097958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label runtime; 3098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4, 3099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &runtime); 3100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compare flat one-byte strings. Returns when done. 3102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (equality) { 3103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, 3104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier tmp2); 3105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 3106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1, 3107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier tmp2, tmp3); 3108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Handle more complex cases in runtime. 3111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&runtime); 3112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (equality) { 31133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 31143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 31153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Push(left, right); 31163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CallRuntime(Runtime::kStringEqual); 31173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 31183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadRoot(r4, Heap::kTrueValueRootIndex); 31193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ sub(r3, r3, r4); 31203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Ret(); 3121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 31223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Push(left, right); 3123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kStringCompare); 3124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 3127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 3128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CompareICStub::GenerateReceivers(MacroAssembler* masm) { 3132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(CompareICState::RECEIVER, state()); 3133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 3134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(r5, r4, r3); 3135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r5, &miss); 3136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 3138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r3, r5, r5, FIRST_JS_RECEIVER_TYPE); 3139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blt(&miss); 3140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r4, r5, r5, FIRST_JS_RECEIVER_TYPE); 3141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blt(&miss); 3142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(GetCondition() == eq); 3144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ sub(r3, r3, r4); 3145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 3146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 3148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 3149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CompareICStub::GenerateKnownReceivers(MacroAssembler* masm) { 3153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 3154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<WeakCell> cell = Map::WeakCellForMap(known_map_); 3155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(r5, r4, r3); 3156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r5, &miss); 3157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ GetWeakValue(r7, cell); 3158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset)); 3159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset)); 3160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r5, r7); 3161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss); 3162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r6, r7); 3163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(&miss); 3164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (Token::IsEqualityOp(op())) { 3166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(r3, r3, r4); 3167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 3168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 3169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (op() == Token::LT || op() == Token::LTE) { 3170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r5, Smi::FromInt(GREATER)); 3171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 3172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadSmiLiteral(r5, Smi::FromInt(LESS)); 3173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(r4, r3, r5); 3175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kCompare); 3176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 3179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 3180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateMiss(MacroAssembler* masm) { 3184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 3185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call the runtime system in a fresh internal frame. 3186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 3187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(r4, r3); 3188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(r4, r3); 3189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral(r0, Smi::FromInt(op())); 3190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(r0); 3191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCompareIC_Miss); 3192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compute the entry point of the rewritten stub. 3193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r5, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); 3194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore registers. 3195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Pop(r4, r3); 3196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpToJSEntry(r5); 3199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// This stub is paired with DirectCEntryStub::GenerateCall 3203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid DirectCEntryStub::Generate(MacroAssembler* masm) { 3204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Place the return address on the stack, making the call 3205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // GC safe. The RegExp backend also relies on this. 3206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 3207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); 3208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Call(ip); // Call the C++ function. 3209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); 3210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtlr(r0); 3211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blr(); 3212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid DirectCEntryStub::GenerateCall(MacroAssembler* masm, Register target) { 3216109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (ABI_USES_FUNCTION_DESCRIPTORS) { 3217109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // AIX/PPC64BE Linux use a function descriptor. 3218109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(target, kPointerSize)); 3219109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ip, MemOperand(target, 0)); // Instruction address 3220109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 3221109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ip needs to be set for DirectCEentryStub::Generate, and also 3222109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // for ABI_CALL_VIA_IP. 3223109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Move(ip, target); 3224109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier intptr_t code = reinterpret_cast<intptr_t>(GetCode().location()); 3227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r0, Operand(code, RelocInfo::CODE_TARGET)); 3228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Call(r0); // Call the stub. 3229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NameDictionaryLookupStub::GenerateNegativeLookup( 3233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Label* miss, Label* done, Register receiver, 3234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register properties, Handle<Name> name, Register scratch0) { 3235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(name->IsUniqueName()); 3236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If names of slots in range from 1 to kProbes - 1 for the hash value are 3237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // not equal to the name and kProbes-th slot is not used (its name is the 3238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // undefined value), it guarantees the hash table doesn't contain the 3239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // property. It's true even if some slots represent deleted properties 3240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (their names are the hole value). 3241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (int i = 0; i < kInlinedProbes; i++) { 3242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // scratch0 points to properties hash. 3243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compute the masked index: (hash + i + i * i) & mask. 3244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register index = scratch0; 3245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Capacity is smi 2^n. 3246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(index, FieldMemOperand(properties, kCapacityOffset)); 3247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subi(index, index, Operand(1)); 3248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadSmiLiteral( 3249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ip, Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i))); 3250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(index, index, ip); 3251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Scale the index by multiplying by the entry size. 3253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NameDictionary::kEntrySize == 3); 3254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeftImm(ip, index, Operand(1)); 3255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(index, index, ip); // index *= 3. 3256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register entity_name = scratch0; 3258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Having undefined at this place means the name is not contained. 3259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp = properties; 3260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiToPtrArrayOffset(ip, index); 3261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(tmp, properties, ip); 3262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); 3263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!tmp.is(entity_name)); 3265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); 3266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(entity_name, tmp); 3267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(done); 3268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the hole ready for use below: 3270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); 3271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stop if found the property. 3273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Cmpi(entity_name, Operand(Handle<Name>(name)), r0); 3274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(miss); 3275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label good; 3277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(entity_name, tmp); 3278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&good); 3279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if the entry name is not a unique name. 3281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); 3282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(entity_name, FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); 3283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotUniqueNameInstanceType(entity_name, miss); 3284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&good); 3285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore the properties. 3287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(properties, 3288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 3289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int spill_mask = (r0.bit() | r9.bit() | r8.bit() | r7.bit() | r6.bit() | 3292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r5.bit() | r4.bit() | r3.bit()); 3293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 3295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPush(spill_mask); 3296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 3298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r4, Operand(Handle<Name>(name))); 3299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameDictionaryLookupStub stub(masm->isolate(), NEGATIVE_LOOKUP); 3300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallStub(&stub); 3301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r3, Operand::Zero()); 3302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPop(spill_mask); // MultiPop does not touch condition flags 3304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtlr(r0); 3305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(done); 3307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss); 3308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Probe the name dictionary in the |elements| register. Jump to the 3312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// |done| label if a property with the given name is found. Jump to 3313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the |miss| label otherwise. 3314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// If lookup was successful |scratch2| will be equal to elements + 4 * index. 3315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NameDictionaryLookupStub::GeneratePositiveLookup( 3316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Label* miss, Label* done, Register elements, 3317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register name, Register scratch1, Register scratch2) { 3318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!elements.is(scratch1)); 3319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!elements.is(scratch2)); 3320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!name.is(scratch1)); 3321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!name.is(scratch2)); 3322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ AssertName(name); 3324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compute the capacity mask. 3326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch1, FieldMemOperand(elements, kCapacityOffset)); 3327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(scratch1); // convert smi to int 3328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subi(scratch1, scratch1, Operand(1)); 3329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Generate an unrolled loop that performs a few probes before 3331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // giving up. Measurements done on Gmail indicate that 2 probes 3332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // cover ~93% of loads from dictionaries. 3333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (int i = 0; i < kInlinedProbes; i++) { 3334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compute the masked index: (hash + i + i * i) & mask. 3335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwz(scratch2, FieldMemOperand(name, Name::kHashFieldOffset)); 3336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (i > 0) { 3337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Add the probe offset (i + i * i) left shifted to avoid right shifting 3338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the hash in a separate instruction. The value hash + i + i * i is right 3339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // shifted in the following and instruction. 3340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(NameDictionary::GetProbeOffset(i) < 3341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1 << (32 - Name::kHashFieldOffset)); 3342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(scratch2, scratch2, 3343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift)); 3344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ srwi(scratch2, scratch2, Operand(Name::kHashShift)); 3346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(scratch2, scratch1, scratch2); 3347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Scale the index by multiplying by the entry size. 3349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NameDictionary::kEntrySize == 3); 3350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // scratch2 = scratch2 * 3. 3351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeftImm(ip, scratch2, Operand(1)); 3352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(scratch2, scratch2, ip); 3353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if the key is identical to the name. 3355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeftImm(ip, scratch2, Operand(kPointerSizeLog2)); 3356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(scratch2, elements, ip); 3357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(ip, FieldMemOperand(scratch2, kElementsStartOffset)); 3358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(name, ip); 3359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(done); 3360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int spill_mask = (r0.bit() | r9.bit() | r8.bit() | r7.bit() | r6.bit() | 3363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r5.bit() | r4.bit() | r3.bit()) & 3364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ~(scratch1.bit() | scratch2.bit()); 3365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mflr(r0); 3367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPush(spill_mask); 3368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (name.is(r3)) { 3369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!elements.is(r4)); 3370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r4, name); 3371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r3, elements); 3372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 3373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r3, elements); 3374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r4, name); 3375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameDictionaryLookupStub stub(masm->isolate(), POSITIVE_LOOKUP); 3377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallStub(&stub); 3378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(r3, Operand::Zero()); 3379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(scratch2, r5); 3380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ MultiPop(spill_mask); 3381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mtlr(r0); 3382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(done); 3384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(miss); 3385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NameDictionaryLookupStub::Generate(MacroAssembler* masm) { 3389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // This stub overrides SometimesSetsUpAFrame() to return false. That means 3390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // we cannot call anything that could cause a GC from this stub. 3391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Registers: 3392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // result: NameDictionary to probe 3393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r4: key 3394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // dictionary: NameDictionary to probe. 3395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // index: will hold an index of entry if lookup is successful. 3396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // might alias with result_. 3397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Returns: 3398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // result_ is zero if lookup failed, non zero otherwise. 3399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register result = r3; 3401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register dictionary = r3; 3402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register key = r4; 3403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register index = r5; 3404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register mask = r6; 3405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register hash = r7; 3406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register undefined = r8; 3407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register entry_key = r9; 3408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch = r9; 3409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label in_dictionary, maybe_in_dictionary, not_in_dictionary; 3411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(mask, FieldMemOperand(dictionary, kCapacityOffset)); 3413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ SmiUntag(mask); 3414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subi(mask, mask, Operand(1)); 3415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lwz(hash, FieldMemOperand(key, Name::kHashFieldOffset)); 3417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); 3419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (int i = kInlinedProbes; i < kTotalProbes; i++) { 3421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compute the masked index: (hash + i + i * i) & mask. 3422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Capacity is smi 2^n. 3423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (i > 0) { 3424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Add the probe offset (i + i * i) left shifted to avoid right shifting 3425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the hash in a separate instruction. The value hash + i + i * i is right 3426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // shifted in the following and instruction. 3427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(NameDictionary::GetProbeOffset(i) < 3428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1 << (32 - Name::kHashFieldOffset)); 3429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(index, hash, 3430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift)); 3431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 3432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(index, hash); 3433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ srwi(r0, index, Operand(Name::kHashShift)); 3435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(index, mask, r0); 3436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Scale the index by multiplying by the entry size. 3438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NameDictionary::kEntrySize == 3); 3439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeftImm(scratch, index, Operand(1)); 3440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(index, index, scratch); // index *= 3. 3441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ShiftLeftImm(scratch, index, Operand(kPointerSizeLog2)); 3443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(index, dictionary, scratch); 3444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(entry_key, FieldMemOperand(index, kElementsStartOffset)); 3445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Having undefined at this place means the name is not contained. 3447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(entry_key, undefined); 3448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(¬_in_dictionary); 3449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stop if found the property. 3451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(entry_key, key); 3452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&in_dictionary); 3453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) { 3455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if the entry name is not a unique name. 3456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); 3457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(entry_key, FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); 3458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotUniqueNameInstanceType(entry_key, &maybe_in_dictionary); 3459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&maybe_in_dictionary); 3463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If we are doing negative lookup then probing failure should be 3464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // treated as a lookup success. For positive lookup probing failure 3465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // should be treated as lookup failure. 3466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (mode() == POSITIVE_LOOKUP) { 3467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(result, Operand::Zero()); 3468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 3469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&in_dictionary); 3472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(result, Operand(1)); 3473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 3474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(¬_in_dictionary); 3476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ li(result, Operand::Zero()); 3477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 3478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 3482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Isolate* isolate) { 3483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs); 3484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub1.GetCode(); 3485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Hydrogen code stubs need stub2 at snapshot time. 3486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreBufferOverflowStub stub2(isolate, kSaveFPRegs); 3487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier stub2.GetCode(); 3488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Takes the input in 3 registers: address_ value_ and object_. A pointer to 3492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the value has just been written into the object, now this stub makes sure 3493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// we keep the GC informed. The word in the object where the value has been 3494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// written is in the address register. 3495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::Generate(MacroAssembler* masm) { 3496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label skip_to_incremental_noncompacting; 3497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label skip_to_incremental_compacting; 3498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The first two branch instructions are generated with labels so as to 3500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // get the offset fixed up correctly by the bind(Label*) call. We patch 3501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // it back and forth between branch condition True and False 3502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // when we start and stop incremental heap marking. 3503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // See RecordWriteStub::Patch for details. 3504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Clear the bit, branch on True for NOP action initially 3506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ crclr(Assembler::encode_crbit(cr2, CR_LT)); 3507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(&skip_to_incremental_noncompacting, cr2); 3508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(&skip_to_incremental_compacting, cr2); 3509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (remembered_set_action() == EMIT_REMEMBERED_SET) { 3511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 3512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler::kReturnAtEnd); 3513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 3515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&skip_to_incremental_noncompacting); 3517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateIncremental(masm, INCREMENTAL); 3518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&skip_to_incremental_compacting); 3520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateIncremental(masm, INCREMENTAL_COMPACTION); 3521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. 3523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Will be checked in IncrementalMarking::ActivateGeneratedStub. 3524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // patching not required on PPC as the initial path is effectively NOP 3525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { 3529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.Save(masm); 3530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (remembered_set_action() == EMIT_REMEMBERED_SET) { 3532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label dont_need_remembered_set; 3533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0)); 3535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. 3536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.scratch0(), &dont_need_remembered_set); 3537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3538109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfInNewSpace(regs_.object(), regs_.scratch0(), 3539109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch &dont_need_remembered_set); 3540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // First notify the incremental marker if necessary, then update the 3542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // remembered set. 3543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CheckNeedsToInformIncrementalMarker( 3544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); 3545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InformIncrementalMarker(masm); 3546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.Restore(masm); 3547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 3548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler::kReturnAtEnd); 3549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&dont_need_remembered_set); 3551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CheckNeedsToInformIncrementalMarker( 3554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm, kReturnOnNoNeedToInformIncrementalMarker, mode); 3555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InformIncrementalMarker(masm); 3556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.Restore(masm); 3557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 3558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { 3562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode()); 3563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int argument_count = 3; 3564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ PrepareCallCFunction(argument_count, regs_.scratch0()); 3565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register address = 3566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier r3.is(regs_.address()) ? regs_.scratch0() : regs_.address(); 3567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!address.is(regs_.object())); 3568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!address.is(r3)); 3569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(address, regs_.address()); 3570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r3, regs_.object()); 3571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r4, address); 3572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r5, Operand(ExternalReference::isolate_address(isolate()))); 3573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AllowExternalCallThatCantCauseGC scope(masm); 3575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallCFunction( 3576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::incremental_marking_record_write_function(isolate()), 3577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier argument_count); 3578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode()); 3579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::CheckNeedsToInformIncrementalMarker( 3583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, OnNoNeedToInformIncrementalMarker on_no_need, 3584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Mode mode) { 3585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label on_black; 3586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label need_incremental; 3587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label need_incremental_pop_scratch; 3588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0); 3590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lis(r0, Operand((~Page::kPageAlignmentMask >> 16))); 3591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(regs_.scratch0(), regs_.object(), r0); 3592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP( 3593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.scratch1(), 3594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemOperand(regs_.scratch0(), MemoryChunk::kWriteBarrierCounterOffset)); 3595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ subi(regs_.scratch1(), regs_.scratch1(), Operand(1)); 3596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP( 3597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.scratch1(), 3598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemOperand(regs_.scratch0(), MemoryChunk::kWriteBarrierCounterOffset)); 3599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(regs_.scratch1(), Operand::Zero()); // PPC, we could do better here 3600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(&need_incremental); 3601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Let's look at the color of the object: If it is not black we don't have 3603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // to inform the incremental marker. 3604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black); 3605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.Restore(masm); 3607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 3608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 3609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler::kReturnAtEnd); 3610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 3611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 3612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&on_black); 3615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get the value from the slot. 3617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0)); 3618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (mode == INCREMENTAL_COMPACTION) { 3620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label ensure_not_white; 3621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckPageFlag(regs_.scratch0(), // Contains value. 3623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.scratch1(), // Scratch. 3624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemoryChunk::kEvacuationCandidateMask, eq, 3625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &ensure_not_white); 3626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckPageFlag(regs_.object(), 3628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.scratch1(), // Scratch. 3629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemoryChunk::kSkipEvacuationSlotsRecordingMask, eq, 3630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &need_incremental); 3631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&ensure_not_white); 3633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We need extra registers for this, so we push the object and the address 3636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // register temporarily. 3637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(regs_.object(), regs_.address()); 3638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfWhite(regs_.scratch0(), // The value. 3639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch regs_.scratch1(), // Scratch. 3640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch regs_.object(), // Scratch. 3641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch regs_.address(), // Scratch. 3642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &need_incremental_pop_scratch); 3643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Pop(regs_.object(), regs_.address()); 3644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier regs_.Restore(masm); 3646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 3647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 3648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler::kReturnAtEnd); 3649958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 3650958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 3651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&need_incremental_pop_scratch); 3654958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Pop(regs_.object(), regs_.address()); 3655958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&need_incremental); 3657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Fall through when we need to inform the incremental marker. 3659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StubFailureTrampolineStub::Generate(MacroAssembler* masm) { 3663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CEntryStub ces(isolate(), 1, kSaveFPRegs); 3664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); 3665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int parameter_count_offset = 36663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch StubFailureTrampolineFrameConstants::kArgumentsLengthOffset; 3667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(r4, MemOperand(fp, parameter_count_offset)); 3668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (function_mode() == JS_FUNCTION_STUB_MODE) { 3669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ addi(r4, r4, Operand(1)); 3670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); 3672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ slwi(r4, r4, Operand(kPointerSizeLog2)); 3673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(sp, sp, r4); 3674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 3675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid LoadICTrampolineStub::Generate(MacroAssembler* masm) { 3679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister()); 3680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadICStub stub(isolate(), state()); 3681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stub.GenerateForTrampoline(masm); 3682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { 3686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister()); 3687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch KeyedLoadICStub stub(isolate(), state()); 3688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stub.GenerateForTrampoline(masm); 3689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CallICTrampolineStub::Generate(MacroAssembler* masm) { 3693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ EmitLoadTypeFeedbackVector(r5); 3694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallICStub stub(isolate(), state()); 3695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 3696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 3697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LoadICStub::Generate(MacroAssembler* masm) { GenerateImpl(masm, false); } 3700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LoadICStub::GenerateForTrampoline(MacroAssembler* masm) { 3703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateImpl(masm, true); 3704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void HandleArrayCases(MacroAssembler* masm, Register feedback, 3708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register receiver_map, Register scratch1, 3709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch2, bool is_polymorphic, 3710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* miss) { 3711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // feedback initially contains the feedback array 3712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label next_loop, prepare_next; 3713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label start_polymorphic; 3714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register cached_map = scratch1; 3716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(cached_map, 3718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(0))); 3719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset)); 3720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(receiver_map, cached_map); 3721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&start_polymorphic); 3722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // found, now call handler. 3723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register handler = feedback; 3724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(handler, 3725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(1))); 3726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addi(ip, handler, Operand(Code::kHeaderSize - kHeapObjectTag)); 3727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(ip); 3728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register length = scratch2; 3731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&start_polymorphic); 3732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(length, FieldMemOperand(feedback, FixedArray::kLengthOffset)); 3733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!is_polymorphic) { 3734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the IC could be monomorphic we have to make sure we don't go past the 3735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // end of the feedback array. 3736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpSmiLiteral(length, Smi::FromInt(2), r0); 3737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(miss); 3738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register too_far = length; 3741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register pointer_reg = feedback; 3742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3743109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // +-----+------+------+-----+-----+ ... ----+ 3744109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // | map | len | wm0 | h0 | wm1 | hN | 3745109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // +-----+------+------+-----+-----+ ... ----+ 3746109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // 0 1 2 len-1 3747109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ^ ^ 3748109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // | | 3749109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // pointer_reg too_far 3750109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // aka feedback scratch2 3751109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // also need receiver_map 3752109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // use cached_map (scratch1) to look in the weak map values. 3753109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r0, length); 3754109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(too_far, feedback, r0); 3755109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(too_far, too_far, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3756109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(pointer_reg, feedback, 3757109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Operand(FixedArray::OffsetOfElementAt(2) - kHeapObjectTag)); 3758109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3759109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&next_loop); 3760109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(cached_map, MemOperand(pointer_reg)); 3761109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset)); 3762109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(receiver_map, cached_map); 3763109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&prepare_next); 3764109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(handler, MemOperand(pointer_reg, kPointerSize)); 3765109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(ip, handler, Operand(Code::kHeaderSize - kHeapObjectTag)); 3766109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Jump(ip); 3767109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3768109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&prepare_next); 3769109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(pointer_reg, pointer_reg, Operand(kPointerSize * 2)); 3770109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(pointer_reg, too_far); 3771109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ blt(&next_loop); 3772109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3773109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We exhausted our array of map handler pairs. 3774109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(miss); 3775109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3776109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3777109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3778109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void HandleMonomorphicCase(MacroAssembler* masm, Register receiver, 3779109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register receiver_map, Register feedback, 3780109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register vector, Register slot, 3781109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch, Label* compare_map, 3782109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label* load_smi_map, Label* try_array) { 3783109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(receiver, load_smi_map); 3784109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 3785109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(compare_map); 3786109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register cached_map = scratch; 3787109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Move the weak map into the weak_cell register. 3788109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(cached_map, FieldMemOperand(feedback, WeakCell::kValueOffset)); 3789109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(cached_map, receiver_map); 3790109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(try_array); 3791109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register handler = feedback; 3792109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r0, slot); 3793109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(handler, vector, r0); 3794109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(handler, 3795109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(handler, FixedArray::kHeaderSize + kPointerSize)); 3796109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(ip, handler, Operand(Code::kHeaderSize - kHeapObjectTag)); 3797109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Jump(ip); 3798109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3799109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3800109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3801109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid LoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { 3802109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register receiver = LoadWithVectorDescriptor::ReceiverRegister(); // r4 3803109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register name = LoadWithVectorDescriptor::NameRegister(); // r5 3804109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register vector = LoadWithVectorDescriptor::VectorRegister(); // r6 3805109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register slot = LoadWithVectorDescriptor::SlotRegister(); // r3 3806109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register feedback = r7; 3807109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register receiver_map = r8; 3808109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch1 = r9; 3809109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3810109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r0, slot); 3811109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(feedback, vector, r0); 3812109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); 3813109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3814109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Try to quickly handle the monomorphic case without knowing for sure 3815109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // if we have a weak cell in feedback. We do know it's safe to look 3816109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // at WeakCell::kValueOffset. 3817109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label try_array, load_smi_map, compare_map; 3818109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label not_array, miss; 3819109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot, 3820109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch scratch1, &compare_map, &load_smi_map, &try_array); 3821109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3822109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Is it a fixed array? 3823109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&try_array); 3824109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); 3825109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex); 3826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(¬_array); 3827109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch HandleArrayCases(masm, feedback, receiver_map, scratch1, r10, true, &miss); 3828109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3829109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(¬_array); 3830109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex); 3831109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&miss); 3832bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Code::Flags code_flags = 3833bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC)); 3834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags, 3835109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch receiver, name, feedback, 3836109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch receiver_map, scratch1, r10); 3837109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3838109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&miss); 3839109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch LoadIC::GenerateMiss(masm); 3840109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3841109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&load_smi_map); 3842109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); 3843109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&compare_map); 3844109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3845109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3846109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3847109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid KeyedLoadICStub::Generate(MacroAssembler* masm) { 3848109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateImpl(masm, false); 3849109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3850109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3851109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3852109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid KeyedLoadICStub::GenerateForTrampoline(MacroAssembler* masm) { 3853109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateImpl(masm, true); 3854109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3855109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3856109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3857109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { 3858109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register receiver = LoadWithVectorDescriptor::ReceiverRegister(); // r4 3859109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register key = LoadWithVectorDescriptor::NameRegister(); // r5 3860109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register vector = LoadWithVectorDescriptor::VectorRegister(); // r6 3861109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register slot = LoadWithVectorDescriptor::SlotRegister(); // r3 3862109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register feedback = r7; 3863109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register receiver_map = r8; 3864109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch1 = r9; 3865109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3866109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r0, slot); 3867109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(feedback, vector, r0); 3868109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); 3869109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3870109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Try to quickly handle the monomorphic case without knowing for sure 3871109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // if we have a weak cell in feedback. We do know it's safe to look 3872109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // at WeakCell::kValueOffset. 3873109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label try_array, load_smi_map, compare_map; 3874109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label not_array, miss; 3875109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot, 3876109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch scratch1, &compare_map, &load_smi_map, &try_array); 3877109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3878109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&try_array); 3879109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Is it a fixed array? 3880109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); 3881109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex); 3882109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(¬_array); 3883109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3884109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We have a polymorphic element handler. 3885109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label polymorphic, try_poly_name; 3886109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&polymorphic); 3887109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch HandleArrayCases(masm, feedback, receiver_map, scratch1, r10, true, &miss); 3888109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3889109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(¬_array); 3890109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Is it generic? 3891109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex); 3892109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&try_poly_name); 3893109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> megamorphic_stub = 3894109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch KeyedLoadIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState()); 3895109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET); 3896109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3897109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&try_poly_name); 3898109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We might have a name in feedback, and a fixed array in the next slot. 3899109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(key, feedback); 3900109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&miss); 3901109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If the name comparison succeeded, we know we have a fixed array with 3902109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // at least one map/handler pair. 3903109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r0, slot); 3904109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(feedback, vector, r0); 3905109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(feedback, 3906109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(feedback, FixedArray::kHeaderSize + kPointerSize)); 3907109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch HandleArrayCases(masm, feedback, receiver_map, scratch1, r10, false, &miss); 3908109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3909109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&miss); 3910109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch KeyedLoadIC::GenerateMiss(masm); 3911109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3912109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&load_smi_map); 3913109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); 3914109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&compare_map); 3915109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3916109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3917109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3918109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid VectorStoreICTrampolineStub::Generate(MacroAssembler* masm) { 3919109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ EmitLoadTypeFeedbackVector(VectorStoreICDescriptor::VectorRegister()); 3920109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch VectorStoreICStub stub(isolate(), state()); 3921109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stub.GenerateForTrampoline(masm); 3922109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3923109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3925109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid VectorKeyedStoreICTrampolineStub::Generate(MacroAssembler* masm) { 3926109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ EmitLoadTypeFeedbackVector(VectorStoreICDescriptor::VectorRegister()); 3927109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch VectorKeyedStoreICStub stub(isolate(), state()); 3928109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stub.GenerateForTrampoline(masm); 3929109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 3930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3932109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid VectorStoreICStub::Generate(MacroAssembler* masm) { 3933109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateImpl(masm, false); 3934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3937109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid VectorStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { 3938109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateImpl(masm, true); 3939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3942109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { 3943109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // r4 3944109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register key = VectorStoreICDescriptor::NameRegister(); // r5 3945109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register vector = VectorStoreICDescriptor::VectorRegister(); // r6 3946109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register slot = VectorStoreICDescriptor::SlotRegister(); // r7 3947109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(VectorStoreICDescriptor::ValueRegister().is(r3)); // r3 3948109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register feedback = r8; 3949109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register receiver_map = r9; 3950109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch1 = r10; 3951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiToPtrArrayOffset(r0, slot); 3953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(feedback, vector, r0); 3954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); 3955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Try to quickly handle the monomorphic case without knowing for sure 3957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // if we have a weak cell in feedback. We do know it's safe to look 3958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // at WeakCell::kValueOffset. 3959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label try_array, load_smi_map, compare_map; 3960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label not_array, miss; 3961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot, 3962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch scratch1, &compare_map, &load_smi_map, &try_array); 3963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Is it a fixed array? 3965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&try_array); 3966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); 3967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex); 3968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(¬_array); 3969109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3970109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch2 = r11; 3971109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch HandleArrayCases(masm, feedback, receiver_map, scratch1, scratch2, true, 3972109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch &miss); 3973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(¬_array); 3975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex); 3976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&miss); 3977bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Code::Flags code_flags = 3978bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC)); 3979109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch masm->isolate()->stub_cache()->GenerateProbe( 3980109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch masm, Code::STORE_IC, code_flags, receiver, key, feedback, receiver_map, 3981109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch scratch1, scratch2); 3982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&miss); 3984109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch StoreIC::GenerateMiss(masm); 3985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&load_smi_map); 3987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); 3988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&compare_map); 3989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3992109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid VectorKeyedStoreICStub::Generate(MacroAssembler* masm) { 3993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateImpl(masm, false); 3994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3997109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid VectorKeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { 3998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateImpl(masm, true); 3999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 4000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4002109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void HandlePolymorphicStoreCase(MacroAssembler* masm, Register feedback, 4003109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register receiver_map, Register scratch1, 4004109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch2, Label* miss) { 4005109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // feedback initially contains the feedback array 4006109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label next_loop, prepare_next; 4007109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label start_polymorphic; 4008109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label transition_call; 4009109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4010109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register cached_map = scratch1; 4011109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register too_far = scratch2; 4012109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register pointer_reg = feedback; 4013109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(too_far, FieldMemOperand(feedback, FixedArray::kLengthOffset)); 4014109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4015109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // +-----+------+------+-----+-----+-----+ ... ----+ 4016109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // | map | len | wm0 | wt0 | h0 | wm1 | hN | 4017109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // +-----+------+------+-----+-----+ ----+ ... ----+ 4018109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // 0 1 2 len-1 4019109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ^ ^ 4020109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // | | 4021109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // pointer_reg too_far 4022109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // aka feedback scratch2 4023109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // also need receiver_map 4024109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // use cached_map (scratch1) to look in the weak map values. 4025109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r0, too_far); 4026109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(too_far, feedback, r0); 4027109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(too_far, too_far, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 4028109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(pointer_reg, feedback, 4029109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Operand(FixedArray::OffsetOfElementAt(0) - kHeapObjectTag)); 4030109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4031109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&next_loop); 4032109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(cached_map, MemOperand(pointer_reg)); 4033109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset)); 4034109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(receiver_map, cached_map); 4035109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&prepare_next); 4036109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Is it a transitioning store? 4037109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(too_far, MemOperand(pointer_reg, kPointerSize)); 4038109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(too_far, Heap::kUndefinedValueRootIndex); 4039109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&transition_call); 4040109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(pointer_reg, MemOperand(pointer_reg, kPointerSize * 2)); 4041109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(ip, pointer_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); 4042109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Jump(ip); 4043109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4044109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&transition_call); 4045109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(too_far, FieldMemOperand(too_far, WeakCell::kValueOffset)); 4046109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(too_far, miss); 4047109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4048109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(receiver_map, MemOperand(pointer_reg, kPointerSize * 2)); 4049109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4050109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load the map into the correct register. 4051109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(feedback.is(VectorStoreTransitionDescriptor::MapRegister())); 4052109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(feedback, too_far); 4053109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4054109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(ip, receiver_map, Operand(Code::kHeaderSize - kHeapObjectTag)); 4055109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Jump(ip); 4056109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4057109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&prepare_next); 4058109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(pointer_reg, pointer_reg, Operand(kPointerSize * 3)); 4059109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpl(pointer_reg, too_far); 4060109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ blt(&next_loop); 4061109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4062109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We exhausted our array of map handler pairs. 4063109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(miss); 4064109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 4065109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4066109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4067109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid VectorKeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { 4068109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // r4 4069109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register key = VectorStoreICDescriptor::NameRegister(); // r5 4070109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register vector = VectorStoreICDescriptor::VectorRegister(); // r6 4071109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register slot = VectorStoreICDescriptor::SlotRegister(); // r7 4072109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(VectorStoreICDescriptor::ValueRegister().is(r3)); // r3 4073109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register feedback = r8; 4074109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register receiver_map = r9; 4075109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch1 = r10; 4076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiToPtrArrayOffset(r0, slot); 4078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(feedback, vector, r0); 4079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); 4080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Try to quickly handle the monomorphic case without knowing for sure 4082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // if we have a weak cell in feedback. We do know it's safe to look 4083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // at WeakCell::kValueOffset. 4084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label try_array, load_smi_map, compare_map; 4085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label not_array, miss; 4086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot, 4087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch scratch1, &compare_map, &load_smi_map, &try_array); 4088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&try_array); 4090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Is it a fixed array? 4091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); 4092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex); 4093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(¬_array); 4094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We have a polymorphic element handler. 4096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label polymorphic, try_poly_name; 4097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&polymorphic); 4098109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4099109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch2 = r11; 4100109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4101109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch HandlePolymorphicStoreCase(masm, feedback, receiver_map, scratch1, scratch2, 4102109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch &miss); 4103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(¬_array); 4105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Is it generic? 4106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex); 4107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&try_poly_name); 4108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Code> megamorphic_stub = 4109109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState()); 4110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET); 4111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&try_poly_name); 4113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We might have a name in feedback, and a fixed array in the next slot. 4114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(key, feedback); 4115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&miss); 4116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the name comparison succeeded, we know we have a fixed array with 4117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // at least one map/handler pair. 4118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiToPtrArrayOffset(r0, slot); 4119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(feedback, vector, r0); 4120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(feedback, 4121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldMemOperand(feedback, FixedArray::kHeaderSize + kPointerSize)); 4122109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch HandleArrayCases(masm, feedback, receiver_map, scratch1, scratch2, false, 4123109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch &miss); 4124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4125f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&miss); 4126109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch KeyedStoreIC::GenerateMiss(masm); 4127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4128f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&load_smi_map); 4129f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); 4130f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ b(&compare_map); 4131f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 4132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4134109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { 4135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (masm->isolate()->function_entry_hook() != NULL) { 4136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PredictableCodeSizeScope predictable(masm, 4137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if V8_TARGET_ARCH_PPC64 4138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 14 * Assembler::kInstrSize); 4139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else 4140109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 11 * Assembler::kInstrSize); 4141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif 4142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ProfileEntryHookStub stub(masm->isolate()); 4143109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mflr(r0); 4144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r0, ip); 4145109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallStub(&stub); 4146109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(r0, ip); 4147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mtlr(r0); 4148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 41498389745919cae02139ddc085a63c00d024269cf2Ben Murdoch} 4150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ProfileEntryHookStub::Generate(MacroAssembler* masm) { 4153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The entry hook is a "push lr, ip" instruction, followed by a call. 4154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int32_t kReturnAddressDistanceFromFunctionStart = 4155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Assembler::kCallTargetAddressOffset + 3 * Assembler::kInstrSize; 4156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // This should contain all kJSCallerSaved registers. 4158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const RegList kSavedRegs = kJSCallerSaved | // Caller saved registers. 4159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch r15.bit(); // Saved stack pointer. 4160f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 4161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We also save lr, so the count here is one higher than the mask indicates. 4162109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int32_t kNumSavedRegs = kNumJSCallerSaved + 2; 4163109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4164109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Save all caller-save registers as this may be called from anywhere. 4165109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mflr(ip); 4166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ MultiPush(kSavedRegs | ip.bit()); 4167109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Compute the function's address for the first argument. 4169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ subi(r3, ip, Operand(kReturnAddressDistanceFromFunctionStart)); 4170109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4171109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The caller's return address is two slots above the saved temporaries. 4172109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Grab that for the second argument to the hook. 4173109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r4, sp, Operand((kNumSavedRegs + 1) * kPointerSize)); 4174109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4175109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Align the stack if necessary. 4176109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int frame_alignment = masm->ActivationFrameAlignment(); 4177109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (frame_alignment > kPointerSize) { 4178109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r15, sp); 4179109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(base::bits::IsPowerOfTwo32(frame_alignment)); 4180109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment))); 4181109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4182109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4183109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if !defined(USE_SIMULATOR) 4184109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch uintptr_t entry_hook = 4185109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch reinterpret_cast<uintptr_t>(isolate()->function_entry_hook()); 4186109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else 4187109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Under the simulator we need to indirect the entry hook through a 4188109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // trampoline function at a known address. 4189109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); 4190109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference entry_hook = ExternalReference( 4191109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch &dispatcher, ExternalReference::BUILTIN_CALL, isolate()); 4192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4193109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // It additionally takes an isolate as a third parameter 4194109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(r5, Operand(ExternalReference::isolate_address(isolate()))); 4195109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif 4196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4197109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ip, Operand(entry_hook)); 4198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4199109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (ABI_USES_FUNCTION_DESCRIPTORS) { 4200109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(ip, kPointerSize)); 4201109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(ip, MemOperand(ip, 0)); 4202109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4203109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ip set above, so nothing more to do for ABI_CALL_VIA_IP. 4204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4205109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // PPC LINUX ABI: 4206109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ li(r0, Operand::Zero()); 4207109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StorePU(r0, MemOperand(sp, -kNumRequiredStackFrameSlots * kPointerSize)); 4208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4209109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Call(ip); 4210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4211109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(sp, sp, Operand(kNumRequiredStackFrameSlots * kPointerSize)); 4212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4213109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Restore the stack pointer if needed. 4214109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (frame_alignment > kPointerSize) { 4215109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(sp, r15); 4216109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4218109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Also pop lr to get Ret(0). 4219109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ MultiPop(kSavedRegs | ip.bit()); 4220109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mtlr(ip); 4221109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 4222109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 4223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4225109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochtemplate <class T> 4226109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void CreateArrayDispatch(MacroAssembler* masm, 4227109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AllocationSiteOverrideMode mode) { 4228109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (mode == DISABLE_ALLOCATION_SITES) { 4229109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub(masm->isolate(), GetInitialFastElementsKind(), mode); 4230109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub); 4231109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (mode == DONT_OVERRIDE) { 4232109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int last_index = 4233109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); 4234109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i <= last_index; ++i) { 4235109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4236109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Cmpi(r6, Operand(kind), r0); 4237109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub(masm->isolate(), kind); 4238109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub, eq); 4239109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4241109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If we reached this point there is a problem. 4242109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Abort(kUnexpectedElementsKindInArrayConstructor); 4243109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 4244109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch UNREACHABLE(); 4245109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 42468389745919cae02139ddc085a63c00d024269cf2Ben Murdoch} 4247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4249109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void CreateArrayDispatchOneArgument(MacroAssembler* masm, 4250109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AllocationSiteOverrideMode mode) { 4251109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r5 - allocation site (if mode != DISABLE_ALLOCATION_SITES) 4252109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r6 - kind (if mode != DISABLE_ALLOCATION_SITES) 4253109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r3 - number of arguments 4254109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r4 - constructor? 4255109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // sp[0] - last argument 4256109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label normal_sequence; 4257109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (mode == DONT_OVERRIDE) { 4258109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 4259109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 4260109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_ELEMENTS == 2); 4261109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); 4262109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_DOUBLE_ELEMENTS == 4); 4263109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); 4264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4265109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // is the low bit set? If so, we are holey and that is good. 4266109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andi(r0, r6, Operand(1)); 4267109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&normal_sequence, cr0); 4268109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4270109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // look at the first argument 4271109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r8, MemOperand(sp, 0)); 4272109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r8, Operand::Zero()); 4273109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&normal_sequence); 4274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4275109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (mode == DISABLE_ALLOCATION_SITES) { 4276109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind initial = GetInitialFastElementsKind(); 4277109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind holey_initial = GetHoleyElementsKind(initial); 4278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4279109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArraySingleArgumentConstructorStub stub_holey( 4280109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch masm->isolate(), holey_initial, DISABLE_ALLOCATION_SITES); 4281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub_holey); 42828389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4283109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&normal_sequence); 4284109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArraySingleArgumentConstructorStub stub(masm->isolate(), initial, 4285109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DISABLE_ALLOCATION_SITES); 4286109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub); 4287109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (mode == DONT_OVERRIDE) { 4288109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We are going to create a holey array, but our kind is non-holey. 4289109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Fix kind and retry (only if we have an allocation site in the slot). 4290109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r6, r6, Operand(1)); 42918389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4292109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 4293109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r8, FieldMemOperand(r5, 0)); 4294109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex); 4295109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(eq, kExpectedAllocationSite); 4296109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4298109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Save the resulting elements kind in type info. We can't just store r6 4299109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // in the AllocationSite::transition_info field because elements kind is 4300109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // restricted to a portion of the field...upper bits need to be left alone. 4301109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 4302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r7, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset)); 4303109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AddSmiLiteral(r7, r7, Smi::FromInt(kFastElementsKindPackedToHoley), r0); 4304109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r7, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset), 4305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch r0); 4306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&normal_sequence); 4308109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int last_index = 4309109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); 4310109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i <= last_index; ++i) { 4311109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4312109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(r0, Operand(kind)); 4313109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(r6, r0); 4314109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArraySingleArgumentConstructorStub stub(masm->isolate(), kind); 4315109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub, eq); 4316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4318109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If we reached this point there is a problem. 4319109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Abort(kUnexpectedElementsKindInArrayConstructor); 4320109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 4321109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch UNREACHABLE(); 4322109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4323109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 4324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4326109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochtemplate <class T> 4327109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { 4328109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int to_index = 4329109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); 4330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i <= to_index; ++i) { 4331109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4332109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub(isolate, kind); 4333109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stub.GetCode(); 4334109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { 4335109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub1(isolate, kind, DISABLE_ALLOCATION_SITES); 4336109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stub1.GetCode(); 4337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4338109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4339109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 4340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4342109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { 4343109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( 4344109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch isolate); 4345109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( 4346109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch isolate); 4347109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( 4348109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch isolate); 4349f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 4350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4352109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( 4353109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Isolate* isolate) { 4354109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kinds[2] = {FAST_ELEMENTS, FAST_HOLEY_ELEMENTS}; 4355109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i < 2; i++) { 4356109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // For internal arrays we only need a few things 4357109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]); 4358109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stubh1.GetCode(); 4359109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]); 4360109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stubh2.GetCode(); 4361109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); 4362109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stubh3.GetCode(); 4363109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4364109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 4365109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4366109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4367109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ArrayConstructorStub::GenerateDispatchToArrayStub( 4368109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MacroAssembler* masm, AllocationSiteOverrideMode mode) { 4369109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (argument_count() == ANY) { 4370109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label not_zero_case, not_one_case; 4371109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r3, Operand::Zero()); 4372109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(¬_zero_case); 4373109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 4374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4375109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(¬_zero_case); 4376109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r3, Operand(1)); 4377109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bgt(¬_one_case); 4378109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CreateArrayDispatchOneArgument(masm, mode); 4379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4380109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(¬_one_case); 4381109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 4382109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (argument_count() == NONE) { 4383109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 4384109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (argument_count() == ONE) { 4385109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CreateArrayDispatchOneArgument(masm, mode); 4386109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (argument_count() == MORE_THAN_ONE) { 4387109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 4388109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 4389109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch UNREACHABLE(); 4390109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4391109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 4392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4394109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ArrayConstructorStub::Generate(MacroAssembler* masm) { 4395109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 4396109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r3 : argc (only if argument_count() == ANY) 4397109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r4 : constructor 4398109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r5 : AllocationSite or undefined 4399109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r6 : new target 4400109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- sp[0] : return address 4401109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- sp[4] : last argument 4402109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 4403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4404109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 4405109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The array construct code is only set for the global and natives 4406109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // builtin Array functions which always have maps. 4407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4408109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Initial map for the builtin Array function should be a map. 4409109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r7, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); 4410109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Will both indicate a NULL and a Smi. 4411109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TestIfSmi(r7, r0); 4412109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0); 4413109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareObjectType(r7, r7, r8, MAP_TYPE); 4414109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 4415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4416109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We should either have undefined in r5 or a valid AllocationSite 4417109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertUndefinedOrAllocationSite(r5, r7); 4418109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4420109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Enter the context of the Array function. 4421109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); 4422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4423109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label subclassing; 4424109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(r6, r4); 4425109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&subclassing); 4426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4427109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label no_info; 4428109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Get the elements kind and case on that. 4429109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(r5, Heap::kUndefinedValueRootIndex); 4430109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&no_info); 4431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4432109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r6, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset)); 4433109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiUntag(r6); 4434109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 4435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ And(r6, r6, Operand(AllocationSite::ElementsKindBits::kMask)); 4436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); 4437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&no_info); 4439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); 4440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4441109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&subclassing); 4442109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch switch (argument_count()) { 4443109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch case ANY: 4444109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch case MORE_THAN_ONE: 4445109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2)); 4446109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StorePX(r4, MemOperand(sp, r0)); 4447109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r3, r3, Operand(3)); 4448109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch break; 4449109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch case NONE: 4450109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, MemOperand(sp, 0 * kPointerSize)); 4451109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ li(r3, Operand(3)); 4452109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch break; 4453109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch case ONE: 4454109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, MemOperand(sp, 1 * kPointerSize)); 4455109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ li(r3, Operand(4)); 4456109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch break; 4457109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4459109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r6, r5); 4460109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpToExternalReference(ExternalReference(Runtime::kNewArray, isolate())); 4461109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 4462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4464109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InternalArrayConstructorStub::GenerateCase(MacroAssembler* masm, 4465109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kind) { 4466109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpli(r3, Operand(1)); 4467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4468109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArrayNoArgumentConstructorStub stub0(isolate(), kind); 4469109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub0, lt); 4470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArrayNArgumentsConstructorStub stubN(isolate(), kind); 4472109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stubN, gt); 4473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4474109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (IsFastPackedElementsKind(kind)) { 4475109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We might need to create a holey array 4476109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // look at the first argument 4477109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r6, MemOperand(sp, 0)); 4478109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r6, Operand::Zero()); 4479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4480109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArraySingleArgumentConstructorStub stub1_holey( 4481109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch isolate(), GetHoleyElementsKind(kind)); 4482109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub1_holey, ne); 4483f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 4484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4485109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArraySingleArgumentConstructorStub stub1(isolate(), kind); 4486109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub1); 4487109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 4488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 44898389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4490109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InternalArrayConstructorStub::Generate(MacroAssembler* masm) { 4491109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 4492109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r3 : argc 4493109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r4 : constructor 4494109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- sp[0] : return address 4495109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- sp[4] : last argument 4496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 4497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4498109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 4499109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The array construct code is only set for the global and natives 4500109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // builtin Array functions which always have maps. 4501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Initial map for the builtin Array function should be a map. 4503109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r6, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); 4504109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Will both indicate a NULL and a Smi. 4505109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TestIfSmi(r6, r0); 4506109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0); 4507109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareObjectType(r6, r6, r7, MAP_TYPE); 4508109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 4509f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 4510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4511109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Figure out the right elements kind 4512109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r6, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); 4513109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load the map's "bit field 2" into |result|. 4514109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lbz(r6, FieldMemOperand(r6, Map::kBitField2Offset)); 4515109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Retrieve elements_kind from bit field 2. 4516109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ DecodeField<Map::ElementsKindBits>(r6); 4517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4518109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 4519109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label done; 4520109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r6, Operand(FAST_ELEMENTS)); 4521109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&done); 4522109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r6, Operand(FAST_HOLEY_ELEMENTS)); 4523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(eq, kInvalidElementsKindForInternalArrayOrInternalPackedArray); 4524109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done); 4525109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4527109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label fast_elements_case; 4528109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r6, Operand(FAST_ELEMENTS)); 4529109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&fast_elements_case); 4530109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateCase(masm, FAST_HOLEY_ELEMENTS); 4531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4532109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&fast_elements_case); 4533109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateCase(masm, FAST_ELEMENTS); 45348389745919cae02139ddc085a63c00d024269cf2Ben Murdoch} 4535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4536109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FastNewObjectStub::Generate(MacroAssembler* masm) { 4537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 4538109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r4 : target 4539109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r6 : new target 4540109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- cp : context 4541109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- lr : return address 4542109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 4543109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertFunction(r4); 4544109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertReceiver(r6); 4545109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4546109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Verify that the new target is a JSFunction. 4547109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label new_object; 4548109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareObjectType(r6, r5, r5, JS_FUNCTION_TYPE); 4549109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&new_object); 4550109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4551109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load the initial map and verify that it's in fact a map. 4552109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r5, FieldMemOperand(r6, JSFunction::kPrototypeOrInitialMapOffset)); 4553109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(r5, &new_object); 4554109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareObjectType(r5, r3, r3, MAP_TYPE); 4555109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&new_object); 4556109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4557109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Fall back to runtime if the target differs from the new target's 4558109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // initial map constructor. 4559109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, FieldMemOperand(r5, Map::kConstructorOrBackPointerOffset)); 4560109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(r3, r4); 4561109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&new_object); 4562109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4563109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Allocate the JSObject on the heap. 4564109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label allocate, done_allocate; 4565109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lbz(r7, FieldMemOperand(r5, Map::kInstanceSizeOffset)); 4566109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Allocate(r7, r3, r8, r9, &allocate, SIZE_IN_WORDS); 4567109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_allocate); 4568109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4569109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Initialize the JSObject fields. 4570bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ StoreP(r5, FieldMemOperand(r3, JSObject::kMapOffset), r0); 4571109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 4572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ StoreP(r6, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0); 4573bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ StoreP(r6, FieldMemOperand(r3, JSObject::kElementsOffset), r0); 4574109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize); 4575bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ addi(r4, r3, Operand(JSObject::kHeaderSize - kHeapObjectTag)); 45768389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4577109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 4578bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- r3 : result (tagged) 4579109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r4 : result fields (untagged) 4580109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r8 : result end (untagged) 4581109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r5 : initial map 4582109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- cp : context 4583109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- lr : return address 4584109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 4585f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 4586109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Perform in-object slack tracking if requested. 4587109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label slack_tracking; 4588109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(Map::kNoSlackTracking == 0); 4589109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r9, Heap::kUndefinedValueRootIndex); 4590109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lwz(r6, FieldMemOperand(r5, Map::kBitField3Offset)); 4591109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ DecodeField<Map::ConstructionCounter>(r10, r6, SetRC); 4592109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&slack_tracking, cr0); 4593109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 4594109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Initialize all in-object fields with undefined. 4595109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ InitializeFieldsWithFiller(r4, r8, r9); 4596109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 4597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 4598109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&slack_tracking); 4599109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 4600109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Decrease generous allocation count. 4601109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(Map::ConstructionCounter::kNext == 32); 4602109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Add(r6, r6, -(1 << Map::ConstructionCounter::kShift), r0); 4603109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ stw(r6, FieldMemOperand(r5, Map::kBitField3Offset)); 4604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4605109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Initialize the in-object fields with undefined. 4606109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lbz(r7, FieldMemOperand(r5, Map::kUnusedPropertyFieldsOffset)); 4607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ ShiftLeftImm(r7, r7, Operand(kPointerSizeLog2)); 4608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ sub(r7, r8, r7); 4609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ InitializeFieldsWithFiller(r4, r7, r9); 4610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Initialize the remaining (reserved) fields with one pointer filler map. 4612109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r9, Heap::kOnePointerFillerMapRootIndex); 4613109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ InitializeFieldsWithFiller(r4, r8, r9); 46148389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4615109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check if we can finalize the instance size. 4616109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r10, Operand(Map::kSlackTrackingCounterEnd)); 4617109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(ne); 4618f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 4619109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Finalize the instance size. 4620109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 4621109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 4622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r3, r5); 4623109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kFinalizeInstanceSize); 4624109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(r3); 46258389745919cae02139ddc085a63c00d024269cf2Ben Murdoch } 4626109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 4627109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Fall back to %AllocateInNewSpace. 4630109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&allocate); 4631109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 4632109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 4633109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 4634109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ ShiftLeftImm(r7, r7, 4635109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Operand(kPointerSizeLog2 + kSmiTagSize + kSmiShiftSize)); 4636109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r5, r7); 4637109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace); 4638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(r5); 4639109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4640109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lbz(r8, FieldMemOperand(r5, Map::kInstanceSizeOffset)); 4641109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ ShiftLeftImm(r8, r8, Operand(kPointerSizeLog2)); 4642109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r8, r3, r8); 4643bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ subi(r8, r8, Operand(kHeapObjectTag)); 4644109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&done_allocate); 46458389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4646109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Fall back to %NewObject. 4647109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&new_object); 4648109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r4, r6); 4649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallRuntime(Runtime::kNewObject); 4650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 4651f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 4652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FastNewRestParameterStub::Generate(MacroAssembler* masm) { 4653109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 4654109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r4 : function 4655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- cp : context 4656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- fp : frame pointer 4657109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- lr : return address 4658109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 4659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertFunction(r4); 4660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4661bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Make r5 point to the JavaScript frame. 4662bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mr(r5, fp); 4663bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (skip_stub_frame()) { 4664bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // For Ignition we need to skip the handler/stub frame to reach the 4665bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // JavaScript frame for the function. 4666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset)); 4667bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 4668bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (FLAG_debug_code) { 4669bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label ok; 46703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kFunctionOffset)); 4671109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(ip, r4); 4672bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ beq(&ok); 4673bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Abort(kInvalidFrameForFastNewRestArgumentsStub); 4674bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&ok); 46758389745919cae02139ddc085a63c00d024269cf2Ben Murdoch } 4676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4677109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check if we have rest parameters (only possible if we have an 4678109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // arguments adaptor frame below the function frame). 4679109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label no_rest_parameters; 4680109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset)); 46813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadP(ip, MemOperand(r5, CommonFrameConstants::kContextOrFrameTypeOffset)); 4682109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0); 4683109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&no_rest_parameters); 4684109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4685109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check if the arguments adaptor frame contains more arguments than 4686109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // specified by the function's internal formal parameter count. 4687109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label rest_parameters; 4688109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset)); 4689109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r4, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 4690109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadWordArith( 4691109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch r4, FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset)); 4692109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if V8_TARGET_ARCH_PPC64 4693109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(r4); 4694109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif 4695109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ sub(r3, r3, r4, LeaveOE, SetRC); 4696109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bgt(&rest_parameters, cr0); 46978389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4698109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Return an empty rest parameter array. 4699109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&no_rest_parameters); 4700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 4701109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 4702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- cp : context 4703109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- lr : return address 4704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 4705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Allocate an empty rest parameter array. 4707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label allocate, done_allocate; 4708bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Allocate(JSArray::kSize, r3, r4, r5, &allocate, NO_ALLOCATION_FLAGS); 4709109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_allocate); 4710109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4711109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Setup the rest parameter array in r0. 4712109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, r4); 4713109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, FieldMemOperand(r3, JSArray::kMapOffset), r0); 4714109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); 4715109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, FieldMemOperand(r3, JSArray::kPropertiesOffset), r0); 4716109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, FieldMemOperand(r3, JSArray::kElementsOffset), r0); 4717109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ li(r4, Operand::Zero()); 4718109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, FieldMemOperand(r3, JSArray::kLengthOffset), r0); 4719109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); 4720109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 4721109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4722109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Fall back to %AllocateInNewSpace. 4723109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&allocate); 4724109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 4725109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 4726109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(Smi::FromInt(JSArray::kSize)); 4727109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace); 4728f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 4729109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&done_allocate); 4730f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 47318389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4732109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&rest_parameters); 4733109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 4734109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Compute the pointer to the first rest parameter (skippping the receiver). 4735109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r9, r3); 4736109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r5, r5, r9); 4737109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r5, r5, Operand(StandardFrameConstants::kCallerSPOffset)); 4738109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4739109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 4740109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- cp : context 4741109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r3 : number of rest parameters (tagged) 4742109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r5 : pointer just past first rest parameters 4743109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r9 : size of rest parameters 4744109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- lr : return address 4745109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 4746109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4747109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Allocate space for the rest parameter array plus the backing store. 4748109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label allocate, done_allocate; 4749109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(r4, Operand(JSArray::kSize + FixedArray::kHeaderSize)); 4750109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r4, r4, r9); 4751bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Allocate(r4, r6, r7, r8, &allocate, NO_ALLOCATION_FLAGS); 4752109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_allocate); 4753109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4754109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Setup the elements array in r6. 4755109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r4, Heap::kFixedArrayMapRootIndex); 4756109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, FieldMemOperand(r6, FixedArray::kMapOffset), r0); 4757109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r3, FieldMemOperand(r6, FixedArray::kLengthOffset), r0); 4758109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r7, r6, 4759109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize)); 4760109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 4761109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label loop; 4762109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiUntag(r0, r3); 4763109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mtctr(r0); 4764109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&loop); 4765109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadPU(ip, MemOperand(r5, -kPointerSize)); 4766109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StorePU(ip, MemOperand(r7, kPointerSize)); 4767109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bdnz(&loop); 4768109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r7, r7, Operand(kPointerSize)); 4769109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 47708389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4771109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Setup the rest parameter array in r7. 4772109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, r4); 4773109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, MemOperand(r7, JSArray::kMapOffset)); 4774109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); 4775109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, MemOperand(r7, JSArray::kPropertiesOffset)); 4776109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r6, MemOperand(r7, JSArray::kElementsOffset)); 4777109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r3, MemOperand(r7, JSArray::kLengthOffset)); 4778109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); 4779109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r3, r7, Operand(kHeapObjectTag)); 4780109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 4781109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4782109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Fall back to %AllocateInNewSpace. 4783109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&allocate); 4784109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 4785109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 4786109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(r4); 4787109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r3, r5, r4); 4788109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace); 4789109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r6, r3); 4790109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(r3, r5); 4791109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4792109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&done_allocate); 4793109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4794f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 4795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4796109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) { 4797109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 4798109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r4 : function 4799109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- cp : context 4800109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- fp : frame pointer 4801109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- lr : return address 4802109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 4803109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertFunction(r4); 4804109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4805bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Make r10 point to the JavaScript frame. 4806bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mr(r10, fp); 4807bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (skip_stub_frame()) { 4808bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // For Ignition we need to skip the handler/stub frame to reach the 4809bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // JavaScript frame for the function. 4810bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadP(r10, MemOperand(r10, StandardFrameConstants::kCallerFPOffset)); 4811bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 4812bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (FLAG_debug_code) { 4813bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label ok; 4814bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadP(ip, MemOperand(r10, StandardFrameConstants::kFunctionOffset)); 4815bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(ip, r4); 4816bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ beq(&ok); 4817bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Abort(kInvalidFrameForFastNewRestArgumentsStub); 4818bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&ok); 4819bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 4820bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 4821bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 4822109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub. 4823109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 4824109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadWordArith( 4825109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset)); 4826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if V8_TARGET_ARCH_PPC64 4827109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(r5); 4828109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif 4829109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r6, r5); 4830bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ add(r6, r10, r6); 4831109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset)); 4832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r4 : function 4834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r5 : number of parameters (tagged) 4835109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r6 : parameters pointer 4836bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // r10 : JavaScript frame pointer 4837109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Registers used over whole function: 4838109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r8 : arguments count (tagged) 4839109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r9 : mapped parameter count (tagged) 4840109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4841109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check if the calling frame is an arguments adaptor frame. 4842109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label adaptor_frame, try_allocate, runtime; 4843bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadP(r7, MemOperand(r10, StandardFrameConstants::kCallerFPOffset)); 48443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadP(r3, MemOperand(r7, CommonFrameConstants::kContextOrFrameTypeOffset)); 4845109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpSmiLiteral(r3, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0); 4846109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&adaptor_frame); 4847109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4848109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // No adaptor, parameter count = argument count. 4849109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r8, r5); 4850109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r9, r5); 4851109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&try_allocate); 4852109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4853109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We have an adaptor frame. Patch the parameters pointer. 4854109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&adaptor_frame); 4855109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r8, MemOperand(r7, ArgumentsAdaptorFrameConstants::kLengthOffset)); 4856109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r6, r8); 4857109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r6, r6, r7); 4858109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset)); 4859109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4860109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r8 = argument count (tagged) 4861109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r9 = parameter count (tagged) 4862109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Compute the mapped parameter count = min(r5, r8) in r9. 4863109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(r5, r8); 4864109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 4865109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ isel(lt, r9, r5, r8); 4866109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 4867109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label skip; 4868109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r9, r5); 4869109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ blt(&skip); 4870109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r9, r8); 4871109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&skip); 48728389745919cae02139ddc085a63c00d024269cf2Ben Murdoch } 4873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4874109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&try_allocate); 48758389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4876109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Compute the sizes of backing store, parameter map, and arguments object. 4877109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // 1. Parameter map, has 2 extra words containing context and backing store. 4878109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kParameterMapHeaderSize = 4879109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FixedArray::kHeaderSize + 2 * kPointerSize; 4880109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If there are no mapped parameters, we do not need the parameter_map. 4881109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpSmiLiteral(r9, Smi::FromInt(0), r0); 4882109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 4883109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r11, r9); 4884109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r11, r11, Operand(kParameterMapHeaderSize)); 4885109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ isel(eq, r11, r0, r11); 4886109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 4887109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label skip2, skip3; 4888109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&skip2); 4889109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ li(r11, Operand::Zero()); 4890109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&skip3); 4891109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&skip2); 4892109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r11, r9); 4893109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r11, r11, Operand(kParameterMapHeaderSize)); 4894109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&skip3); 4895109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 48968389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4897109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // 2. Backing store. 4898109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r7, r8); 4899109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r11, r11, r7); 4900109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r11, r11, Operand(FixedArray::kHeaderSize)); 49018389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 4902109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // 3. Arguments object. 4903109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r11, r11, Operand(JSSloppyArgumentsObject::kSize)); 4904109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4905109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Do the allocation of all three objects in one go. 4906bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Allocate(r11, r3, r11, r7, &runtime, NO_ALLOCATION_FLAGS); 4907109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4908109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r3 = address of new object(s) (tagged) 4909109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r5 = argument count (smi-tagged) 4910109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Get the arguments boilerplate from the current native context into r4. 4911109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kNormalOffset = 4912109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); 4913109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kAliasedOffset = 4914109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); 4915109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 4916109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r7, NativeContextMemOperand()); 4917109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpi(r9, Operand::Zero()); 4918109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 4919109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r11, MemOperand(r7, kNormalOffset)); 4920109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r7, MemOperand(r7, kAliasedOffset)); 4921109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ isel(eq, r7, r11, r7); 4922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 4923109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label skip4, skip5; 4924109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&skip4); 4925109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r7, MemOperand(r7, kNormalOffset)); 4926109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&skip5); 4927109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&skip4); 4928109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r7, MemOperand(r7, kAliasedOffset)); 4929109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&skip5); 4930958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 4931958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4932109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r3 = address of new object (tagged) 4933109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r5 = argument count (smi-tagged) 4934109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r7 = address of arguments map (tagged) 4935109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r9 = mapped parameter count (tagged) 4936109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r7, FieldMemOperand(r3, JSObject::kMapOffset), r0); 4937109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r11, Heap::kEmptyFixedArrayRootIndex); 4938109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r11, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0); 4939109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r11, FieldMemOperand(r3, JSObject::kElementsOffset), r0); 4940958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4941109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Set up the callee in-object property. 4942109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertNotSmi(r4); 4943109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, FieldMemOperand(r3, JSSloppyArgumentsObject::kCalleeOffset), 4944109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch r0); 4945958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4946109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Use the length (smi tagged) and set that as an in-object property too. 4947109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertSmi(r8); 4948109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r8, FieldMemOperand(r3, JSSloppyArgumentsObject::kLengthOffset), 4949109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch r0); 4950958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4951109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Set up the elements pointer in the allocated arguments object. 4952109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If we allocated a parameter map, r7 will point there, otherwise 4953109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // it will point to the backing store. 4954109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r7, r3, Operand(JSSloppyArgumentsObject::kSize)); 4955109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0); 4956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4957109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r3 = address of new object (tagged) 4958109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r5 = argument count (tagged) 4959109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r7 = address of parameter map or backing store (tagged) 4960109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r9 = mapped parameter count (tagged) 4961109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Initialize parameter map. If there are no mapped arguments, we're done. 4962109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label skip_parameter_map; 4963109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpSmiLiteral(r9, Smi::FromInt(0), r0); 4964109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 4965109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ isel(eq, r4, r7, r4); 4966109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&skip_parameter_map); 4967109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 4968109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label skip6; 4969109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(&skip6); 4970109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Move backing store address to r4, because it is 4971109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // expected there when filling in the unmapped arguments. 4972109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r4, r7); 4973109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&skip_parameter_map); 4974109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&skip6); 4975958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 4976958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4977109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r8, Heap::kSloppyArgumentsElementsMapRootIndex); 4978109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r8, FieldMemOperand(r7, FixedArray::kMapOffset), r0); 4979109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AddSmiLiteral(r8, r9, Smi::FromInt(2), r0); 4980109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r8, FieldMemOperand(r7, FixedArray::kLengthOffset), r0); 4981109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(cp, FieldMemOperand(r7, FixedArray::kHeaderSize + 0 * kPointerSize), 4982109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch r0); 4983109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r8, r9); 4984109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r8, r8, r7); 4985109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r8, r8, Operand(kParameterMapHeaderSize)); 4986109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r8, FieldMemOperand(r7, FixedArray::kHeaderSize + 1 * kPointerSize), 4987109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch r0); 4988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 4989109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Copy the parameter slots and the holes in the arguments. 4990109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We need to fill in mapped_parameter_count slots. They index the context, 4991109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // where parameters are stored in reverse order, at 4992109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 4993109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The mapped parameter thus need to get indices 4994109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // MIN_CONTEXT_SLOTS+parameter_count-1 .. 4995109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count 4996109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We loop from right to left. 4997109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label parameters_loop; 4998109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r8, r9); 4999109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AddSmiLiteral(r11, r5, Smi::FromInt(Context::MIN_CONTEXT_SLOTS), r0); 5000109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ sub(r11, r11, r9); 5001109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 5002109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r4, r8); 5003109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r4, r4, r7); 5004109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r4, r4, Operand(kParameterMapHeaderSize)); 5005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5006109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r4 = address of backing store (tagged) 5007109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r7 = address of parameter map (tagged) 5008109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r8 = temporary scratch (a.o., for address calculation) 5009109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r10 = temporary scratch (a.o., for address calculation) 5010109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ip = the hole value 5011109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiUntag(r8); 5012109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mtctr(r8); 5013109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ ShiftLeftImm(r8, r8, Operand(kPointerSizeLog2)); 5014109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r10, r4, r8); 5015109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r8, r7, r8); 5016109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r10, r10, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 5017109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r8, r8, Operand(kParameterMapHeaderSize - kHeapObjectTag)); 5018958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5019109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(¶meters_loop); 5020109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StorePU(r11, MemOperand(r8, -kPointerSize)); 5021109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StorePU(ip, MemOperand(r10, -kPointerSize)); 5022109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AddSmiLiteral(r11, r11, Smi::FromInt(1), r0); 5023109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bdnz(¶meters_loop); 5024958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5025109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Restore r8 = argument count (tagged). 5026109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r8, FieldMemOperand(r3, JSSloppyArgumentsObject::kLengthOffset)); 5027958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5028109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&skip_parameter_map); 5029109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r3 = address of new object (tagged) 5030109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r4 = address of backing store (tagged) 5031109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r8 = argument count (tagged) 5032109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r9 = mapped parameter count (tagged) 5033109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r11 = scratch 5034109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Copy arguments header and remaining slots (if there are any). 5035109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r11, Heap::kFixedArrayMapRootIndex); 5036109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r11, FieldMemOperand(r4, FixedArray::kMapOffset), r0); 5037109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r8, FieldMemOperand(r4, FixedArray::kLengthOffset), r0); 5038109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ sub(r11, r8, r9, LeaveOE, SetRC); 5039109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(eq, cr0); 5040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5041109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label arguments_loop; 5042109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiUntag(r11); 5043109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mtctr(r11); 5044958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5045109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r0, r9); 5046109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ sub(r6, r6, r0); 5047109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r11, r4, r0); 5048109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r11, r11, 5049109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize)); 5050958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5051109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&arguments_loop); 5052109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadPU(r7, MemOperand(r6, -kPointerSize)); 5053109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StorePU(r7, MemOperand(r11, kPointerSize)); 5054109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bdnz(&arguments_loop); 5055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5056109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Return. 5057109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 5058958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5059109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Do the runtime call to allocate the arguments object. 5060109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r8 = argument count (tagged) 5061109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&runtime); 5062109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r4, r6, r8); 5063109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallRuntime(Runtime::kNewSloppyArguments); 5064f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 5065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5066109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { 50678389745919cae02139ddc085a63c00d024269cf2Ben Murdoch // ----------- S t a t e ------------- 5068109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r4 : function 5069109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- cp : context 5070109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- fp : frame pointer 5071109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- lr : return address 50728389745919cae02139ddc085a63c00d024269cf2Ben Murdoch // ----------------------------------- 5073109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertFunction(r4); 5074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5075bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Make r5 point to the JavaScript frame. 5076bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mr(r5, fp); 5077bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (skip_stub_frame()) { 5078bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // For Ignition we need to skip the handler/stub frame to reach the 5079bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // JavaScript frame for the function. 5080109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset)); 5081bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 5082bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (FLAG_debug_code) { 5083bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label ok; 50843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kFunctionOffset)); 5085109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(ip, r4); 5086bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ b(&ok); 5087bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Abort(kInvalidFrameForFastNewRestArgumentsStub); 5088bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&ok); 5089109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 5090f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 5091109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check if we have an arguments adaptor frame below the function frame. 5092109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label arguments_adaptor, arguments_done; 5093109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r6, MemOperand(r5, StandardFrameConstants::kCallerFPOffset)); 50943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadP(ip, MemOperand(r6, CommonFrameConstants::kContextOrFrameTypeOffset)); 5095109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0); 5096109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&arguments_adaptor); 5097109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 5098109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r4, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 5099109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadWordArith( 5100109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch r3, 5101109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset)); 5102109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if V8_TARGET_ARCH_PPC64 5103109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(r3); 5104109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif 5105109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r9, r3); 5106109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r5, r5, r9); 5107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 5108109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&arguments_done); 5109109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&arguments_adaptor); 5110109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 5111109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(r3, MemOperand(r6, ArgumentsAdaptorFrameConstants::kLengthOffset)); 5112109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToPtrArrayOffset(r9, r3); 5113109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r5, r6, r9); 5114109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 5115109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&arguments_done); 5116109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r5, r5, Operand(StandardFrameConstants::kCallerSPOffset)); 5117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5118109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 5119109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- cp : context 5120109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r3 : number of rest parameters (tagged) 5121109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r5 : pointer just past first rest parameters 5122109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- r9 : size of rest parameters 5123109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- lr : return address 5124109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 5125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5126109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Allocate space for the strict arguments object plus the backing store. 5127109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label allocate, done_allocate; 5128109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(r4, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize)); 5129109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ add(r4, r4, r9); 5130bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Allocate(r4, r6, r7, r8, &allocate, NO_ALLOCATION_FLAGS); 5131109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_allocate); 5132109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 5133109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Setup the elements array in r6. 5134109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r4, Heap::kFixedArrayMapRootIndex); 5135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, FieldMemOperand(r6, FixedArray::kMapOffset), r0); 5136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r3, FieldMemOperand(r6, FixedArray::kLengthOffset), r0); 5137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r7, r6, 5138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize)); 5139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 5140109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label loop, done_loop; 5141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiUntag(r0, r3, SetRC); 5142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ beq(&done_loop, cr0); 5143109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mtctr(r0); 5144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&loop); 5145109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadPU(ip, MemOperand(r5, -kPointerSize)); 5146109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StorePU(ip, MemOperand(r7, kPointerSize)); 5147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bdnz(&loop); 5148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_loop); 5149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r7, r7, Operand(kPointerSize)); 51508389745919cae02139ddc085a63c00d024269cf2Ben Murdoch } 5151f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 5152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Setup the rest parameter array in r7. 5153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, r4); 5154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, MemOperand(r7, JSStrictArgumentsObject::kMapOffset)); 5155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); 5156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, MemOperand(r7, JSStrictArgumentsObject::kPropertiesOffset)); 5157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r6, MemOperand(r7, JSStrictArgumentsObject::kElementsOffset)); 5158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r3, MemOperand(r7, JSStrictArgumentsObject::kLengthOffset)); 5159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize); 5160109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r3, r7, Operand(kHeapObjectTag)); 5161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 5162f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 5163109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Fall back to %AllocateInNewSpace. 5164109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&allocate); 5165109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 5166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 5167109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(r4); 5168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r3, r5, r4); 5169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace); 5170109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r6, r3); 5171109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(r3, r5); 5172109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 5173109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(&done_allocate); 5174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 5175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { 5177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register context = cp; 5178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register result = r3; 5179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register slot = r5; 5180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Go up the context chain to the script context. 5182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < depth(); ++i) { 5183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(result, ContextMemOperand(context, Context::PREVIOUS_INDEX)); 5184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context = result; 5185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 5186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the PropertyCell value at the specified slot. 5188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ShiftLeftImm(r0, slot, Operand(kPointerSizeLog2)); 5189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(result, context, r0); 5190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(result, ContextMemOperand(result)); 5191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset)); 5192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the result is not the_hole, return. Otherwise, handle in the runtime. 5194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 5195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(ne); 5196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Fallback to runtime. 5198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiTag(slot); 5199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(slot); 5200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kLoadGlobalViaContext); 5201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 5202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { 5205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register value = r3; 5206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register slot = r5; 5207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register cell = r4; 5209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register cell_details = r6; 5210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register cell_value = r7; 5211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register cell_value_map = r8; 5212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch = r9; 5213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register context = cp; 5215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register context_temp = cell; 5216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label fast_heapobject_case, fast_smi_case, slow_case; 5218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_debug_code) { 5220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(value, Heap::kTheHoleValueRootIndex); 5221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Check(ne, kUnexpectedValue); 5222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 5223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Go up the context chain to the script context. 5225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < depth(); i++) { 5226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(context_temp, ContextMemOperand(context, Context::PREVIOUS_INDEX)); 5227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context = context_temp; 5228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 5229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the PropertyCell at the specified slot. 5231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ShiftLeftImm(r0, slot, Operand(kPointerSizeLog2)); 5232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(cell, context, r0); 5233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(cell, ContextMemOperand(cell)); 5234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load PropertyDetails for the cell (actually only the cell_type and kind). 5236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(cell_details, FieldMemOperand(cell, PropertyCell::kDetailsOffset)); 5237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(cell_details); 5238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ andi(cell_details, cell_details, 5239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Operand(PropertyDetails::PropertyCellTypeField::kMask | 5240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyDetails::KindField::kMask | 5241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyDetails::kAttributesReadOnlyMask)); 5242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if PropertyCell holds mutable data. 5244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label not_mutable_data; 5245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(cell_details, Operand(PropertyDetails::PropertyCellTypeField::encode( 5246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyCellType::kMutable) | 5247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyDetails::KindField::encode(kData))); 5248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(¬_mutable_data); 5249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(value, &fast_smi_case); 5250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&fast_heapobject_case); 5252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(value, FieldMemOperand(cell, PropertyCell::kValueOffset), r0); 5253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // RecordWriteField clobbers the value register, so we copy it before the 5254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // call. 5255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r6, value); 5256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ RecordWriteField(cell, PropertyCell::kValueOffset, r6, scratch, 5257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 5258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch OMIT_SMI_CHECK); 5259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 5260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(¬_mutable_data); 5262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if PropertyCell value matches the new value (relevant for Constant, 5263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ConstantType and Undefined cells). 5264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label not_same_value; 5265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(cell_value, FieldMemOperand(cell, PropertyCell::kValueOffset)); 5266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(cell_value, value); 5267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(¬_same_value); 5268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make sure the PropertyCell is not marked READ_ONLY. 5270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ andi(r0, cell_details, Operand(PropertyDetails::kAttributesReadOnlyMask)); 5271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&slow_case, cr0); 5272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_debug_code) { 5274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 5275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // This can only be true for Constant, ConstantType and Undefined cells, 5276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // because we never store the_hole via this stub. 5277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(cell_details, 5278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Operand(PropertyDetails::PropertyCellTypeField::encode( 5279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyCellType::kConstant) | 5280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyDetails::KindField::encode(kData))); 5281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&done); 5282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(cell_details, 5283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Operand(PropertyDetails::PropertyCellTypeField::encode( 5284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyCellType::kConstantType) | 5285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyDetails::KindField::encode(kData))); 5286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&done); 5287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(cell_details, 5288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Operand(PropertyDetails::PropertyCellTypeField::encode( 5289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyCellType::kUndefined) | 5290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyDetails::KindField::encode(kData))); 5291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Check(eq, kUnexpectedValue); 5292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 5293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 5294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 5295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(¬_same_value); 5296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if PropertyCell contains data with constant type (and is not 5298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // READ_ONLY). 5299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(cell_details, Operand(PropertyDetails::PropertyCellTypeField::encode( 5300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyCellType::kConstantType) | 5301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyDetails::KindField::encode(kData))); 5302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&slow_case); 5303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Now either both old and new values must be smis or both must be heap 5305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // objects with same map. 5306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label value_is_heap_object; 5307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfNotSmi(value, &value_is_heap_object); 5308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfNotSmi(cell_value, &slow_case); 5309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Old and new values are smis, no need for a write barrier here. 5310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&fast_smi_case); 5311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(value, FieldMemOperand(cell, PropertyCell::kValueOffset), r0); 5312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 5313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&value_is_heap_object); 5315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(cell_value, &slow_case); 5316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(cell_value_map, FieldMemOperand(cell_value, HeapObject::kMapOffset)); 5318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); 5319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(cell_value_map, scratch); 5320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&fast_heapobject_case); 5321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Fallback to runtime. 5323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&slow_case); 5324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiTag(slot); 5325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(slot, value); 5326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(is_strict(language_mode()) 5327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ? Runtime::kStoreGlobalViaContext_Strict 5328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : Runtime::kStoreGlobalViaContext_Sloppy); 5329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 5330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic int AddressOffset(ExternalReference ref0, ExternalReference ref1) { 5333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return ref0.address() - ref1.address(); 5334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 5335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Calls an API function. Allocates HandleScope, extracts returned value 5338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// from handle and propagates exceptions. Restores context. stack_space 5339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// - space to be unwound on exit (includes the call JS arguments space and 5340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// the additional space allocated for the fast call). 5341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void CallApiFunctionAndReturn(MacroAssembler* masm, 5342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register function_address, 5343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference thunk_ref, 5344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int stack_space, 5345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand* stack_space_operand, 5346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand return_value_operand, 5347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand* context_restore_operand) { 5348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate* isolate = masm->isolate(); 5349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference next_address = 5350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::handle_scope_next_address(isolate); 5351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kNextOffset = 0; 5352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kLimitOffset = AddressOffset( 5353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::handle_scope_limit_address(isolate), next_address); 5354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kLevelOffset = AddressOffset( 5355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::handle_scope_level_address(isolate), next_address); 5356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Additional parameter is the address of the actual callback. 5358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(function_address.is(r4) || function_address.is(r5)); 5359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch = r6; 5360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch, Operand(ExternalReference::is_profiling_address(isolate))); 5362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lbz(scratch, MemOperand(scratch, 0)); 5363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(scratch, Operand::Zero()); 5364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (CpuFeatures::IsSupported(ISELECT)) { 5366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch, Operand(thunk_ref)); 5367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ isel(eq, scratch, function_address, scratch); 5368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 5369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label profiler_disabled; 5370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label end_profiler_check; 5371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ beq(&profiler_disabled); 5372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch, Operand(thunk_ref)); 5373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&end_profiler_check); 5374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&profiler_disabled); 5375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(scratch, function_address); 5376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&end_profiler_check); 5377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 5378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Allocate HandleScope in callee-save registers. 5380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r17 - next_address 5381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r14 - next_address->kNextOffset 5382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r15 - next_address->kLimitOffset 5383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r16 - next_address->kLevelOffset 5384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r17, Operand(next_address)); 5385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r14, MemOperand(r17, kNextOffset)); 5386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r15, MemOperand(r17, kLimitOffset)); 5387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lwz(r16, MemOperand(r17, kLevelOffset)); 5388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addi(r16, r16, Operand(1)); 5389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ stw(r16, MemOperand(r17, kLevelOffset)); 5390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_log_timer_events) { 5392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope frame(masm, StackFrame::MANUAL); 5393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushSafepointRegisters(); 5394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PrepareCallCFunction(1, r3); 5395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); 5396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallCFunction(ExternalReference::log_enter_external_function(isolate), 5397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1); 5398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopSafepointRegisters(); 5399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 5400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Native call returns to the DirectCEntry stub which redirects to the 5402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // return address pushed on stack (could have moved after GC). 5403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // DirectCEntry stub itself is generated early and never moves. 5404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DirectCEntryStub stub(isolate); 5405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stub.GenerateCall(masm, scratch); 5406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_log_timer_events) { 5408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope frame(masm, StackFrame::MANUAL); 5409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushSafepointRegisters(); 5410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PrepareCallCFunction(1, r3); 5411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); 5412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallCFunction(ExternalReference::log_leave_external_function(isolate), 5413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1); 5414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopSafepointRegisters(); 5415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 5416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label promote_scheduled_exception; 5418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label delete_allocated_handles; 5419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label leave_exit_frame; 5420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label return_value_loaded; 5421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // load value from ReturnValue 5423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r3, return_value_operand); 5424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&return_value_loaded); 5425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // No more valid handles (the result handle was the last one). Restore 5426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // previous handle scope. 5427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(r14, MemOperand(r17, kNextOffset)); 5428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (__ emit_debug_code()) { 5429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lwz(r4, MemOperand(r17, kLevelOffset)); 5430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, r16); 5431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall); 5432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 5433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ subi(r16, r16, Operand(1)); 5434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ stw(r16, MemOperand(r17, kLevelOffset)); 5435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r0, MemOperand(r17, kLimitOffset)); 5436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r15, r0); 5437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&delete_allocated_handles); 5438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Leave the API exit frame. 5440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&leave_exit_frame); 5441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool restore_context = context_restore_operand != NULL; 5442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (restore_context) { 5443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(cp, *context_restore_operand); 5444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 5445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // LeaveExitFrame expects unwind space to be in a register. 5446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (stack_space_operand != NULL) { 5447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lwz(r14, *stack_space_operand); 5448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 5449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r14, Operand(stack_space)); 5450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 5451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LeaveExitFrame(false, r14, !restore_context, stack_space_operand != NULL); 5452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if the function scheduled an exception. 5454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r14, Heap::kTheHoleValueRootIndex); 5455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r15, Operand(ExternalReference::scheduled_exception_address(isolate))); 5456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(r15, MemOperand(r15)); 5457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r14, r15); 5458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(&promote_scheduled_exception); 5459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ blr(); 5461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Re-throw by promoting a scheduled exception. 5463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&promote_scheduled_exception); 5464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kPromoteScheduledException); 5465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // HandleScope limit has changed. Delete allocated extensions. 5467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&delete_allocated_handles); 5468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreP(r15, MemOperand(r17, kLimitOffset)); 5469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r14, r3); 5470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PrepareCallCFunction(1, r15); 5471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); 5472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate), 5473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1); 5474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mr(r3, r14); 5475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&leave_exit_frame); 5476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 5477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 54783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid CallApiCallbackStub::Generate(MacroAssembler* masm) { 5479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------- S t a t e ------------- 5480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r3 : callee 5481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r7 : call_data 5482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r5 : holder 5483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r4 : api_function_address 5484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- cp : context 5485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- 5486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- sp[0] : last argument 5487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- ... 5488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- sp[(argc - 1)* 4] : first argument 5489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- sp[argc * 4] : receiver 5490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------------------------------- 5491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register callee = r3; 5493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register call_data = r7; 5494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder = r5; 5495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register api_function_address = r4; 5496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register context = cp; 5497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier typedef FunctionCallbackArguments FCA; 5499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kContextSaveIndex == 6); 5501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kCalleeIndex == 5); 5502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kDataIndex == 4); 5503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kReturnValueOffset == 3); 5504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 5505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kIsolateIndex == 1); 5506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(FCA::kHolderIndex == 0); 5507bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(FCA::kNewTargetIndex == 7); 5508bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(FCA::kArgsLength == 8); 5509bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5510bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // new target 5511bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 5512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // context save 5514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(context); 55153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (!is_lazy()) { 5516109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // load context from callee 5517109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(context, FieldMemOperand(callee, JSFunction::kContextOffset)); 5518109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 5519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // callee 5521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(callee); 5522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // call data 5524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(call_data); 5525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch = call_data; 55273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (!call_data_undefined()) { 5528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 5529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 5530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // return value 5531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(scratch); 5532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // return value default 5533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(scratch); 5534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // isolate 5535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch, Operand(ExternalReference::isolate_address(masm->isolate()))); 5536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(scratch); 5537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // holder 5538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(holder); 5539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Prepare arguments. 5541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(scratch, sp); 5542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Allocate the v8::Arguments structure in the arguments' space since 5544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // it's not controlled by GC. 5545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // PPC LINUX ABI: 5546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // 5547bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Create 4 extra slots on stack: 5548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // [0] space for DirectCEntryStub's LR save 5549bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // [1-3] FunctionCallbackInfo 5550bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch const int kApiStackSpace = 4; 5551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kFunctionCallbackInfoOffset = 5552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (kStackFrameExtraParamSlot + 1) * kPointerSize; 5553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameScope frame_scope(masm, StackFrame::MANUAL); 5555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ EnterExitFrame(false, kApiStackSpace); 5556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!api_function_address.is(r3) && !scratch.is(r3)); 5558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r3 = FunctionCallbackInfo& 5559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Arguments is after the return address. 5560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addi(r3, sp, Operand(kFunctionCallbackInfoOffset)); 5561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // FunctionCallbackInfo::implicit_args_ 5562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ StoreP(scratch, MemOperand(r3, 0 * kPointerSize)); 55633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // FunctionCallbackInfo::values_ 55643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ addi(ip, scratch, Operand((FCA::kArgsLength - 1 + argc()) * kPointerSize)); 55653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ StoreP(ip, MemOperand(r3, 1 * kPointerSize)); 55663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // FunctionCallbackInfo::length_ = argc 55673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ li(ip, Operand(argc())); 55683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ stw(ip, MemOperand(r3, 2 * kPointerSize)); 5569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference thunk_ref = 5571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::invoke_function_callback(masm->isolate()); 5572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AllowExternalCallThatCantCauseGC scope(masm); 5574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemOperand context_restore_operand( 5575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier fp, (2 + FCA::kContextSaveIndex) * kPointerSize); 5576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stores return the first js argument 5577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int return_value_offset = 0; 55783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (is_store()) { 5579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return_value_offset = 2 + FCA::kArgsLength; 5580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 5581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return_value_offset = 2 + FCA::kReturnValueOffset; 5582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 5583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemOperand return_value_operand(fp, return_value_offset * kPointerSize); 5584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int stack_space = 0; 5585bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MemOperand length_operand = 5586bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize); 5587bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MemOperand* stack_space_operand = &length_operand; 55883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch stack_space = argc() + FCA::kArgsLength + 1; 55893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch stack_space_operand = NULL; 5590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space, 5591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stack_space_operand, return_value_operand, 5592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &context_restore_operand); 5593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 5594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CallApiGetterStub::Generate(MacroAssembler* masm) { 5597109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int arg0Slot = 0; 5598109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int accessorInfoSlot = 0; 5599109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int apiStackSpace = 0; 5600bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Build v8::PropertyCallbackInfo::args_ array on the stack and push property 5601bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // name below the exit frame to make GC aware of them. 5602bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0); 5603bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1); 5604bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2); 5605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3); 5606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4); 5607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5); 5608bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6); 5609bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7); 5610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5611bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register receiver = ApiGetterDescriptor::ReceiverRegister(); 5612bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register holder = ApiGetterDescriptor::HolderRegister(); 5613bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register callback = ApiGetterDescriptor::CallbackRegister(); 5614bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register scratch = r7; 5615bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!AreAliased(receiver, holder, callback, scratch)); 5616bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5617bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register api_function_address = r5; 5618bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5619bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(receiver); 5620bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Push data from AccessorInfo. 5621bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kDataOffset)); 5622bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(scratch); 5623bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 5624bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(scratch, scratch); 5625bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(scratch, Operand(ExternalReference::isolate_address(isolate()))); 5626bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(scratch, holder); 5627bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(Smi::FromInt(0)); // should_throw_on_error -> false 5628bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kNameOffset)); 5629bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(scratch); 5630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5631109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // v8::PropertyCallbackInfo::args_ array and name handle. 5632109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; 5633109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 5634109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load address of v8::PropertyAccessorInfo::args_ array and name handle. 5635109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mr(r3, sp); // r3 = Handle<Name> 5636109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r4, r3, Operand(1 * kPointerSize)); // r4 = v8::PCI::args_ 5637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// If ABI passes Handles (pointer-sized struct) in a register: 5639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// 5640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Create 2 extra slots on stack: 5641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// [0] space for DirectCEntryStub's LR save 5642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// [1] AccessorInfo& 5643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// 5644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Otherwise: 5645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// 5646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Create 3 extra slots on stack: 5647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// [0] space for DirectCEntryStub's LR save 5648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// [1] copy of Handle (first arg) 5649958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// [2] AccessorInfo& 5650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (ABI_PASSES_HANDLES_IN_REGS) { 5651109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch accessorInfoSlot = kStackFrameExtraParamSlot + 1; 5652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch apiStackSpace = 2; 5653109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 5654109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch arg0Slot = kStackFrameExtraParamSlot + 1; 5655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch accessorInfoSlot = arg0Slot + 1; 5656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch apiStackSpace = 3; 5657109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 5658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameScope frame_scope(masm, StackFrame::MANUAL); 5660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ EnterExitFrame(false, apiStackSpace); 5661f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 5662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!ABI_PASSES_HANDLES_IN_REGS) { 5663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // pass 1st arg by reference 5664109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r3, MemOperand(sp, arg0Slot * kPointerSize)); 5665109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r3, sp, Operand(arg0Slot * kPointerSize)); 5666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 5667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5668109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Create v8::PropertyCallbackInfo object on the stack and initialize 5669109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // it's args_ field. 5670109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ StoreP(r4, MemOperand(sp, accessorInfoSlot * kPointerSize)); 5671109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ addi(r4, sp, Operand(accessorInfoSlot * kPointerSize)); 5672109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r4 = v8::PropertyCallbackInfo& 5673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference thunk_ref = 5675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::invoke_accessor_getter_callback(isolate()); 5676109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 5677bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kJsGetterOffset)); 5678bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadP(api_function_address, 5679bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch FieldMemOperand(scratch, Foreign::kForeignAddressOffset)); 5680bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5681109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // +3 is to skip prolog, return address and name handle. 5682109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MemOperand return_value_operand( 5683109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize); 5684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, 5685109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kStackUnwindSpace, NULL, return_value_operand, NULL); 5686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 5687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef __ 5689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 5690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 5691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif // V8_TARGET_ARCH_PPC 5693