13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/simulator-arm.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h" 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ masm. 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(USE_SIMULATOR) 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbyte* fast_exp_arm_machine_code = NULL; 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble fast_exp_simulator(double x) { 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Simulator::current(Isolate::Current())->CallFPReturnsDouble( 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fast_exp_arm_machine_code, x, 0); 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochUnaryMathFunction CreateExpFunction() { 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!FLAG_fast_math) return &std::exp; 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t actual_size; 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte* buffer = 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (buffer == NULL) return &std::exp; 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::InitializeMathExpData(); 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size)); 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister input = d0; 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister result = d1; 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_scratch1 = d2; 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_scratch2 = d3; 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp1 = r4; 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp2 = r5; 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp3 = r6; 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (masm.use_eabi_hardfloat()) { 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Input value is in d0 anyway, nothing to do. 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmov(input, r0, r1); 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(temp3, temp2, temp1); 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MathExpGenerator::EmitMathExp( 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &masm, input, result, double_scratch1, double_scratch2, 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch temp1, temp2, temp3); 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(temp3, temp2, temp1); 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (masm.use_eabi_hardfloat()) { 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmov(d0, result); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmov(r0, r1, result); 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeDesc desc; 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm.GetCode(&desc); 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!RelocInfo::RequiresRelocation(desc)); 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CpuFeatures::FlushICache(buffer, actual_size); 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::ProtectCode(buffer, actual_size); 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if !defined(USE_SIMULATOR) 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return FUNCTION_CAST<UnaryMathFunction>(buffer); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fast_exp_arm_machine_code = buffer; 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return &fast_exp_simulator; 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(V8_HOST_ARCH_ARM) 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub) { 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(USE_SIMULATOR) 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return stub; 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) return stub; 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t actual_size; 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte* buffer = 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (buffer == NULL) return stub; 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size)); 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dest = r0; 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register src = r1; 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register chars = r2; 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp1 = r3; 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label less_4; 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CpuFeatures::IsSupported(NEON)) { 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop, less_256, less_128, less_64, less_32, _16_or_less, _8_or_less; 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label size_less_than_8; 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pld(MemOperand(src, 0)); 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(chars, Operand(8)); 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(lt, &size_less_than_8); 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(chars, Operand(32)); 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(lt, &less_32); 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CpuFeatures::cache_line_size() == 32) { 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pld(MemOperand(src, 32)); 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(chars, Operand(64)); 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(lt, &less_64); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pld(MemOperand(src, 64)); 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CpuFeatures::cache_line_size() == 32) { 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pld(MemOperand(src, 96)); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(chars, Operand(128)); 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(lt, &less_128); 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pld(MemOperand(src, 128)); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CpuFeatures::cache_line_size() == 32) { 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pld(MemOperand(src, 160)); 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pld(MemOperand(src, 192)); 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CpuFeatures::cache_line_size() == 32) { 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pld(MemOperand(src, 224)); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(chars, Operand(256)); 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(lt, &less_256); 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(chars, chars, Operand(256)); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pld(MemOperand(src, 256)); 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex)); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CpuFeatures::cache_line_size() == 32) { 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pld(MemOperand(src, 256)); 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex)); 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(chars, chars, Operand(64), SetCC); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex)); 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex)); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ge, &loop); 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(chars, chars, Operand(256)); 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&less_256); 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex)); 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex)); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(chars, chars, Operand(128)); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex)); 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex)); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex)); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex)); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex)); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex)); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(chars, Operand(64)); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(lt, &less_64); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&less_128); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex)); 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex)); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(chars, chars, Operand(64)); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex)); 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex)); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&less_64); 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(chars, Operand(32)); 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(lt, &less_32); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex)); 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex)); 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(chars, chars, Operand(32)); 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&less_32); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(chars, Operand(16)); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(le, &_16_or_less); 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(src, PostIndex)); 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(dest, PostIndex)); 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(chars, chars, Operand(16)); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&_16_or_less); 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(chars, Operand(8)); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(le, &_8_or_less); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src, PostIndex)); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d0), NeonMemOperand(dest, PostIndex)); 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(chars, chars, Operand(8)); 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do a last copy which may overlap with the previous copy (up to 8 bytes). 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&_8_or_less); 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ rsb(chars, chars, Operand(8)); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(src, src, Operand(chars)); 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(dest, dest, Operand(chars)); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src)); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon8, NeonListOperand(d0), NeonMemOperand(dest)); 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&size_less_than_8); 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bic(temp1, chars, Operand(0x3), SetCC); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&less_4, eq); 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(temp1, MemOperand(src, 4, PostIndex)); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(temp1, MemOperand(dest, 4, PostIndex)); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp2 = ip; 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop; 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bic(temp2, chars, Operand(0x3), SetCC); 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&less_4, eq); 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(temp2, dest, temp2); 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(temp1, MemOperand(src, 4, PostIndex)); 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(temp1, MemOperand(dest, 4, PostIndex)); 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(dest, temp2); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&loop, ne); 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&less_4); 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(chars, Operand(chars, LSL, 31), SetCC); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit0 => Z (ne), bit1 => C (cs) 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrh(temp1, MemOperand(src, 2, PostIndex), cs); 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ strh(temp1, MemOperand(dest, 2, PostIndex), cs); 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(temp1, MemOperand(src), ne); 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ strb(temp1, MemOperand(dest), ne); 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeDesc desc; 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm.GetCode(&desc); 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!RelocInfo::RequiresRelocation(desc)); 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CpuFeatures::FlushICache(buffer, actual_size); 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::ProtectCode(buffer, actual_size); 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return FUNCTION_CAST<MemCopyUint8Function>(buffer); 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Convert 8 to 16. The number of character to copy must be at least 8. 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function( 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemCopyUint16Uint8Function stub) { 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(USE_SIMULATOR) 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return stub; 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) return stub; 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t actual_size; 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte* buffer = 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (buffer == NULL) return stub; 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size)); 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dest = r0; 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register src = r1; 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register chars = r2; 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CpuFeatures::IsSupported(NEON)) { 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = r3; 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop; 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bic(temp, chars, Operand(0x7)); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(chars, chars, Operand(temp)); 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(temp, dest, Operand(temp, LSL, 1)); 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop); 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src, PostIndex)); 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmovl(NeonU8, q0, d0); 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon16, NeonListOperand(d0, 2), NeonMemOperand(dest, PostIndex)); 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(dest, temp); 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&loop, ne); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do a last copy which will overlap with the previous copy (1 to 8 bytes). 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ rsb(chars, chars, Operand(8)); 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(src, src, Operand(chars)); 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(dest, dest, Operand(chars, LSL, 1)); 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src)); 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmovl(NeonU8, q0, d0); 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vst1(Neon16, NeonListOperand(d0, 2), NeonMemOperand(dest)); 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp1 = r3; 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp2 = ip; 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp3 = lr; 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp4 = r4; 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop; 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_two; 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(lr, r4); 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bic(temp2, chars, Operand(0x3)); 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(temp2, dest, Operand(temp2, LSL, 1)); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop); 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(temp1, MemOperand(src, 4, PostIndex)); 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ uxtb16(temp3, Operand(temp1, ROR, 0)); 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ uxtb16(temp4, Operand(temp1, ROR, 8)); 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pkhbt(temp1, temp3, Operand(temp4, LSL, 16)); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(temp1, MemOperand(dest)); 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pkhtb(temp1, temp4, Operand(temp3, ASR, 16)); 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(temp1, MemOperand(dest, 4)); 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(dest, dest, Operand(8)); 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(dest, temp2); 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&loop, ne); 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(chars, Operand(chars, LSL, 31), SetCC); // bit0 => ne, bit1 => cs 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(¬_two, cc); 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrh(temp1, MemOperand(src, 2, PostIndex)); 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ uxtb(temp3, Operand(temp1, ROR, 8)); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp3, Operand(temp3, LSL, 16)); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ uxtab(temp3, temp3, Operand(temp1, ROR, 0)); 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(temp3, MemOperand(dest, 4, PostIndex)); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_two); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(temp1, MemOperand(src), ne); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ strh(temp1, MemOperand(dest), ne); 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(pc, r4); 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeDesc desc; 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm.GetCode(&desc); 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CpuFeatures::FlushICache(buffer, actual_size); 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::ProtectCode(buffer, actual_size); 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return FUNCTION_CAST<MemCopyUint16Uint8Function>(buffer); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochUnaryMathFunction CreateSqrtFunction() { 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(USE_SIMULATOR) 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return &std::sqrt; 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t actual_size; 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte* buffer = 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (buffer == NULL) return &std::sqrt; 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size)); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ MovFromFloatParameter(d0); 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vsqrt(d0, d0); 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ MovToFloatResult(d0); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeDesc desc; 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm.GetCode(&desc); 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!RelocInfo::RequiresRelocation(desc)); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CpuFeatures::FlushICache(buffer, actual_size); 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::ProtectCode(buffer, actual_size); 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return FUNCTION_CAST<UnaryMathFunction>(buffer); 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// ------------------------------------------------------------------------- 3557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Platform-specific RuntimeCallHelper functions. 3567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->EnterFrame(StackFrame::INTERNAL); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!masm->has_frame()); 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->set_has_frame(true); 3617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 3627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->LeaveFrame(StackFrame::INTERNAL); 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(masm->has_frame()); 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->set_has_frame(false); 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// ------------------------------------------------------------------------- 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Code generators 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm) 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ElementsTransitionGenerator::GenerateMapChangeElementsTransition( 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver, 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key, 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register target_map, 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteMode mode, 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* allocation_memento_found) { 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch_elements = r4; 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(receiver, key, value, target_map, 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch_elements)); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode == TRACK_ALLOCATION_SITE) { 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(allocation_memento_found != NULL); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfJSArrayHasAllocationMemento( 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch receiver, scratch_elements, allocation_memento_found); 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set transitioned map. 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(receiver, 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HeapObject::kMapOffset, 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch target_map, 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r9, 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasNotBeenSaved, 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ElementsTransitionGenerator::GenerateSmiToDouble( 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver, 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key, 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register target_map, 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteMode mode, 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fail) { 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Register lr contains the return address. 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry, convert_hole, gc_required, only_change_map, done; 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements = r4; 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register length = r5; 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register array = r6; 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register array_end = array; 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // target_map parameter can be clobbered. 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1 = target_map; 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2 = r9; 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Verify input registers don't conflict with locals. 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(receiver, key, value, target_map, 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements, length, array, scratch2)); 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode == TRACK_ALLOCATION_SITE) { 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail); 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for empty arrays, which only require a map transition and no changes 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // to the backing store. 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex); 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &only_change_map); 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(lr); 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(length, FieldMemOperand(elements, FixedArray::kLengthOffset)); 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // length: number of elements (smi-tagged) 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate new FixedDoubleArray. 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use lr as a temporary register. 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(lr, Operand(length, LSL, 2)); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(lr, lr, Operand(FixedDoubleArray::kHeaderSize)); 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(lr, array, elements, scratch2, &gc_required, DOUBLE_ALIGNMENT); 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // array: destination FixedDoubleArray, not tagged as heap object. 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r4: source FixedArray. 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set destination FixedDoubleArray's length and map. 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(scratch2, Heap::kFixedDoubleArrayMapRootIndex); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(length, MemOperand(array, FixedDoubleArray::kLengthOffset)); 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update receiver's map. 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(scratch2, MemOperand(array, HeapObject::kMapOffset)); 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(receiver, 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HeapObject::kMapOffset, 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch target_map, 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2, 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasBeenSaved, 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_REMEMBERED_SET, 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Replace receiver's backing store with newly created FixedDoubleArray. 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(scratch1, array, Operand(kHeapObjectTag)); 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset)); 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(receiver, 4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSObject::kElementsOffset, 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch1, 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2, 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasBeenSaved, 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Prepare for conversion loop. 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(scratch2, array, Operand(FixedDoubleArray::kHeaderSize)); 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(array_end, scratch2, Operand(length, LSL, 2)); 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Repurpose registers no longer in use. 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register hole_lower = elements; 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register hole_upper = length; 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(hole_lower, Operand(kHoleNanLower32)); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(hole_upper, Operand(kHoleNanUpper32)); 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch1: begin of source FixedArray element fields, not tagged 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // hole_lower: kHoleNanLower32 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // hole_upper: kHoleNanUpper32 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // array_end: end of destination FixedDoubleArray, not tagged 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch2: begin of FixedDoubleArray element fields, not tagged 4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&only_change_map); 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(receiver, 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HeapObject::kMapOffset, 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch target_map, 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2, 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasNotBeenSaved, 5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_REMEMBERED_SET, 5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&done); 5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call into runtime if GC is required. 5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&gc_required); 5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(lr); 5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(fail); 5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Convert and copy elements. 5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(lr, MemOperand(scratch1, 4, PostIndex)); 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // lr: current element 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ UntagAndJumpIfNotSmi(lr, lr, &convert_hole); 5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Normal smi, convert to double and store. 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmov(s0, lr); 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vcvt_f64_s32(d0, s0); 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vstr(d0, scratch2, 0); 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(scratch2, scratch2, Operand(8)); 5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Hole found, store the-hole NaN. 5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&convert_hole); 5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore a "smi-untagged" heap object. 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(lr); 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orr(lr, lr, Operand(1)); 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(lr, Heap::kTheHoleValueRootIndex); 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(eq, kObjectFoundInSmiOnlyArray); 5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Strd(hole_lower, hole_upper, MemOperand(scratch2, 8, PostIndex)); 5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(scratch2, array_end); 5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(lt, &loop); 5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(lr); 5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ElementsTransitionGenerator::GenerateDoubleToObject( 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver, 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key, 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register target_map, 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteMode mode, 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fail) { 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Register lr contains the return address. 5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label entry, loop, convert_hole, gc_required, only_change_map; 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements = r4; 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register array = r6; 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register length = r5; 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = r9; 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Verify input registers don't conflict with locals. 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(receiver, key, value, target_map, 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements, array, length, scratch)); 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode == TRACK_ALLOCATION_SITE) { 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail); 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for empty arrays, which only require a map transition and no changes 5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // to the backing store. 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex); 5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &only_change_map); 5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(lr); 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(target_map, receiver, key, value); 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(length, FieldMemOperand(elements, FixedArray::kLengthOffset)); 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // elements: source FixedDoubleArray 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // length: number of elements (smi-tagged) 5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate new FixedArray. 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Re-use value and target_map registers, as they have been saved on the 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stack. 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register array_size = value; 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register allocate_scratch = target_map; 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(array_size, Operand(FixedDoubleArray::kHeaderSize)); 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(array_size, array_size, Operand(length, LSL, 1)); 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(array_size, array, allocate_scratch, scratch, &gc_required, 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NO_ALLOCATION_FLAGS); 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // array: destination FixedArray, not tagged as heap object 5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set destination FixedDoubleArray's length and map. 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex); 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(length, MemOperand(array, FixedDoubleArray::kLengthOffset)); 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(scratch, MemOperand(array, HeapObject::kMapOffset)); 5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Prepare for conversion loop. 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register src_elements = elements; 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dst_elements = target_map; 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dst_end = length; 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register heap_number_map = scratch; 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(src_elements, elements, 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4)); 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(dst_elements, array, Operand(FixedArray::kHeaderSize)); 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(array, array, Operand(kHeapObjectTag)); 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(dst_end, dst_elements, Operand(length, LSL, 1)); 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Using offsetted addresses in src_elements to fully take advantage of 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // post-indexing. 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // dst_elements: begin of destination FixedArray element fields, not tagged 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // src_elements: begin of source FixedDoubleArray element fields, 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // not tagged, +4 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // dst_end: end of destination FixedArray, not tagged 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // array: destination FixedArray 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // heap_number_map: heap number map 6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call into runtime if GC is required. 6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&gc_required); 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(target_map, receiver, key, value); 6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(lr); 6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(fail); 6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register upper_bits = key; 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(upper_bits, MemOperand(src_elements, 8, PostIndex)); 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // upper_bits: current element's upper 32 bit 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // src_elements: address of next element's upper 32 bit 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(upper_bits, Operand(kHoleNanUpper32)); 6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &convert_hole); 6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Non-hole double, copy value into a heap number. 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register heap_number = receiver; 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2 = value; 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateHeapNumber(heap_number, scratch2, lr, heap_number_map, 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &gc_required); 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // heap_number: new heap number 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch2, MemOperand(src_elements, 12, NegOffset)); 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Strd(scratch2, upper_bits, 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(heap_number, HeapNumber::kValueOffset)); 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch2, dst_elements); 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(heap_number, MemOperand(dst_elements, 4, PostIndex)); 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWrite(array, 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2, 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_number, 6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasBeenSaved, 6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Replace the-hole NaN with the-hole pointer. 6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&convert_hole); 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(scratch2, Heap::kTheHoleValueRootIndex); 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(scratch2, MemOperand(dst_elements, 4, PostIndex)); 6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(dst_elements, dst_end); 6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(lt, &loop); 6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(target_map, receiver, key, value); 6643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Replace receiver's backing store with newly created and filled FixedArray. 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(array, FieldMemOperand(receiver, JSObject::kElementsOffset)); 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(receiver, 6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSObject::kElementsOffset, 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch array, 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch, 6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasBeenSaved, 6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(lr); 6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&only_change_map); 6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update receiver's map. 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(receiver, 6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HeapObject::kMapOffset, 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch target_map, 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch, 6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasNotBeenSaved, 6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_REMEMBERED_SET, 6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StringCharLoadGenerator::Generate(MacroAssembler* masm, 6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register string, 6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index, 6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result, 6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* call_runtime) { 6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fetch the instance type of the receiver into result register. 6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset)); 6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); 6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We need special handling for indirect strings. 7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label check_sequential; 7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(result, Operand(kIsIndirectStringMask)); 7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &check_sequential); 7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Dispatch on the indirect string shape: slice or cons. 7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label cons_string; 7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(result, Operand(kSlicedNotConsMask)); 7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &cons_string); 7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle slices. 7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label indirect_string_loaded; 7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, FieldMemOperand(string, SlicedString::kOffsetOffset)); 7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(string, FieldMemOperand(string, SlicedString::kParentOffset)); 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(index, index, Operand::SmiUntag(result)); 7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&indirect_string_loaded); 7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle cons strings. 7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check whether the right hand side is the empty string (i.e. if 7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // this is really a flat string in a cons string). If that is not 7193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the case we would rather go to the runtime system now to flatten 7203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the string. 7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&cons_string); 7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, FieldMemOperand(string, ConsString::kSecondOffset)); 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(result, Heap::kempty_stringRootIndex); 7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, call_runtime); 7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the first of the two strings and load its instance type. 7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(string, FieldMemOperand(string, ConsString::kFirstOffset)); 7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&indirect_string_loaded); 7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset)); 7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); 7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Distinguish sequential and external strings. Only these two string 7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // representations can reach here (slices and flat cons strings have been 7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // reduced to the underlying sequential or external string). 7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label external_string, check_encoding; 7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_sequential); 7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSeqStringTag == 0); 7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(result, Operand(kStringRepresentationMask)); 7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &external_string); 7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Prepare sequential strings 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(string, 7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch string, 7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&check_encoding); 7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle external strings. 7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&external_string); 7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert that we do not have a cons or slice (indirect strings) here. 7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sequential strings have already been ruled out. 7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(result, Operand(kIsIndirectStringMask)); 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(eq, kExternalStringExpectedButNotFound); 7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Rule out short external strings. 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kShortExternalStringTag != 0); 7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(result, Operand(kShortExternalStringMask)); 7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, call_runtime); 7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(string, FieldMemOperand(string, ExternalString::kResourceDataOffset)); 7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label one_byte, done; 7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_encoding); 7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kTwoByteStringTag == 0); 7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(result, Operand(kStringEncodingMask)); 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &one_byte); 7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Two-byte string. 7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldrh(result, MemOperand(string, index, LSL, 1)); 7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&one_byte); 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // One-byte string. 7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldrb(result, MemOperand(string, index)); 7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic MemOperand ExpConstant(int index, Register base) { 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MemOperand(base, index * kDoubleSize); 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MathExpGenerator::EmitMathExp(MacroAssembler* masm, 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister input, 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister result, 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_scratch1, 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister double_scratch2, 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp1, 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp2, 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp3) { 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!input.is(result)); 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!input.is(double_scratch1)); 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!input.is(double_scratch2)); 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result.is(double_scratch1)); 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result.is(double_scratch2)); 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!double_scratch1.is(double_scratch2)); 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!temp1.is(temp2)); 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!temp1.is(temp3)); 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!temp2.is(temp3)); 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ExternalReference::math_exp_constants(0).address() != NULL); 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!masm->serializer_enabled()); // External references not serializable. 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label zero, infinity, done; 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp3, Operand(ExternalReference::math_exp_constants(0))); 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldr(double_scratch1, ExpConstant(0, temp3)); 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ VFPCompareAndSetFlags(double_scratch1, input); 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ge, &zero); 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldr(double_scratch2, ExpConstant(1, temp3)); 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ VFPCompareAndSetFlags(input, double_scratch2); 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ge, &infinity); 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldr(double_scratch1, ExpConstant(3, temp3)); 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldr(result, ExpConstant(4, temp3)); 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmul(double_scratch1, double_scratch1, input); 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vadd(double_scratch1, double_scratch1, result); 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ VmovLow(temp2, double_scratch1); 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vsub(double_scratch1, double_scratch1, result); 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldr(result, ExpConstant(6, temp3)); 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldr(double_scratch2, ExpConstant(5, temp3)); 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmul(double_scratch1, double_scratch1, double_scratch2); 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vsub(double_scratch1, double_scratch1, input); 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vsub(result, result, double_scratch1); 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmul(double_scratch2, double_scratch1, double_scratch1); 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmul(result, result, double_scratch2); 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldr(double_scratch2, ExpConstant(7, temp3)); 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmul(result, result, double_scratch2); 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vsub(result, result, double_scratch1); 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1. 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(*reinterpret_cast<double*> 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (ExternalReference::math_exp_constants(8).address()) == 1); 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmov(double_scratch2, 1); 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vadd(result, result, double_scratch2); 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp1, Operand(temp2, LSR, 11)); 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ubfx(temp2, temp2, 0, 11); 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(temp1, temp1, Operand(0x3ff)); 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Must not call ExpConstant() after overwriting temp3! 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp3, Operand(ExternalReference::math_exp_log_table())); 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(temp3, temp3, Operand(temp2, LSL, 3)); 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldm(ia, temp3, temp2.bit() | temp3.bit()); 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The first word is loaded is the lower number register. 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (temp2.code() < temp3.code()) { 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orr(temp1, temp3, Operand(temp1, LSL, 20)); 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmov(double_scratch1, temp2, temp1); 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orr(temp1, temp2, Operand(temp1, LSL, 20)); 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmov(double_scratch1, temp3, temp1); 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmul(result, result, double_scratch1); 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&done); 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&zero); 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmov(result, kDoubleRegZero); 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&done); 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&infinity); 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldr(result, ExpConstant(2, temp3)); 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef __ 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// add(r0, pc, Operand(-8)) 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const uint32_t kCodeAgePatchFirstInstruction = 0xe24f0008; 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCodeAgingHelper::CodeAgingHelper() { 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Since patcher is a large object, allocate it dynamically when needed, 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to avoid overloading the stack in stress conditions. 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // DONT_FLUSH is used because the CodeAgingHelper is initialized early in 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the process, before ARM simulator ICache is setup. 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmartPointer<CodePatcher> patcher( 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new CodePatcher(young_sequence_.start(), 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch young_sequence_.length() / Assembler::kInstrSize, 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodePatcher::DONT_FLUSH)); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PredictableCodeSizeScope scope(patcher->masm(), young_sequence_.length()); 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher->masm()->PushFixedFrame(r1); 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher->masm()->nop(ip.code()); 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher->masm()->add( 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool CodeAgingHelper::IsOld(byte* candidate) const { 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Memory::uint32_at(candidate) == kCodeAgePatchFirstInstruction; 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Code::IsYoungSequence(Isolate* isolate, byte* sequence) { 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool result = isolate->code_aging_helper()->IsYoung(sequence); 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result || isolate->code_aging_helper()->IsOld(sequence)); 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age, 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MarkingParity* parity) { 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsYoungSequence(isolate, sequence)) { 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *age = kNoAgeCodeAge; 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *parity = NO_MARKING_PARITY; 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address target_address = Memory::Address_at( 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sequence + (kNoCodeAgeSequenceLength - Assembler::kInstrSize)); 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* stub = GetCodeFromTargetAddress(target_address); 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetCodeAgeAndParity(stub, age, parity); 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Code::PatchPlatformCodeAge(Isolate* isolate, 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte* sequence, 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::Age age, 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MarkingParity parity) { 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t young_length = isolate->code_aging_helper()->young_sequence_length(); 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (age == kNoAgeCodeAge) { 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->code_aging_helper()->CopyYoungSequenceTo(sequence); 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CpuFeatures::FlushICache(sequence, young_length); 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* stub = GetCodeAgeStub(isolate, age, parity); 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodePatcher patcher(sequence, young_length / Assembler::kInstrSize); 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.masm()->add(r0, pc, Operand(-8)); 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.masm()->ldr(pc, MemOperand(pc, -4)); 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.masm()->emit_code_stub_address(stub); 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 938