13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h" 333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "macro-assembler.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// ------------------------------------------------------------------------- 397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Platform-specific RuntimeCallHelper functions. 407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { 423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->EnterFrame(StackFrame::INTERNAL); 433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!masm->has_frame()); 443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->set_has_frame(true); 457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { 493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->LeaveFrame(StackFrame::INTERNAL); 503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(masm->has_frame()); 513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->set_has_frame(false); 527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ masm. 563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 583ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochUnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type) { 593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t actual_size; 603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate buffer in executable space. 613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB, 623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &actual_size, 633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch true)); 643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (buffer == NULL) { 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fallback to library function if function cannot be created. 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch switch (type) { 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case TranscendentalCache::SIN: return &sin; 683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case TranscendentalCache::COS: return &cos; 693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case TranscendentalCache::TAN: return &tan; 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case TranscendentalCache::LOG: return &log; 713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch default: UNIMPLEMENTED(); 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size)); 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // xmm0: raw double input. 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Move double input into registers. 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(rbx); 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(rdi); 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, xmm0); 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(rbx); 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fld_d(Operand(rsp, 0)); 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TranscendentalCacheStub::GenerateOperation(&masm, type); 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The return value is expected to be in xmm0. 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fstp_d(Operand(rsp, 0)); 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(rbx); 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(xmm0, rbx); 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(rdi); 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(rbx); 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeDesc desc; 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm.GetCode(&desc); 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(desc.reloc_size == 0); 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CPU::FlushICache(buffer, actual_size); 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::ProtectCode(buffer, actual_size); 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return FUNCTION_CAST<UnaryMathFunction>(buffer); 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochUnaryMathFunction CreateSqrtFunction() { 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t actual_size; 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate buffer in executable space. 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB, 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &actual_size, 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch true)); 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (buffer == NULL) return &sqrt; 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size)); 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // xmm0: raw double input. 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Move double input into registers. 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sqrtsd(xmm0, xmm0); 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeDesc desc; 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm.GetCode(&desc); 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(desc.reloc_size == 0); 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CPU::FlushICache(buffer, actual_size); 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::ProtectCode(buffer, actual_size); 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return FUNCTION_CAST<UnaryMathFunction>(buffer); 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef _WIN64 1273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocktypedef double (*ModuloFunction)(double, double); 1283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Define custom fmod implementation. 1293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockModuloFunction CreateModuloFunction() { 1303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block size_t actual_size; 1313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, 1323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block &actual_size, 1333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block true)); 1343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CHECK(buffer); 1358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Assembler masm(NULL, buffer, static_cast<int>(actual_size)); 1363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Generated code is put into a fixed, unmovable, buffer, and not into 1373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // the V8 heap. We can't, and don't, refer to any relocatable addresses 1383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // (e.g. the JavaScript nan-object). 1393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Windows 64 ABI passes double arguments in xmm0, xmm1 and 1413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // returns result in xmm0. 1423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Argument backing space is allocated on the stack above 1433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // the return address. 1443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Compute x mod y. 1463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Load y and x (use argument backing store as temporary storage). 1473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movsd(Operand(rsp, kPointerSize * 2), xmm1); 1483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movsd(Operand(rsp, kPointerSize), xmm0); 1493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fld_d(Operand(rsp, kPointerSize * 2)); 1503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fld_d(Operand(rsp, kPointerSize)); 1513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Clear exception flags before operation. 1533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { 1543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label no_exceptions; 1553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fwait(); 1563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fnstsw_ax(); 1573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Clear if Illegal Operand or Zero Division exceptions are set. 1583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ testb(rax, Immediate(5)); 1593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(zero, &no_exceptions); 1603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fnclex(); 1613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&no_exceptions); 1623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Compute st(0) % st(1) 1653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { 1663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label partial_remainder_loop; 1673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&partial_remainder_loop); 1683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fprem(); 1693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fwait(); 1703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fnstsw_ax(); 1713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ testl(rax, Immediate(0x400 /* C2 */)); 1723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If C2 is set, computation only has partial result. Loop to 1733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // continue computation. 1743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &partial_remainder_loop); 1753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label valid_result; 1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label return_result; 1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If Invalid Operand or Zero Division exceptions are set, 1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // return NaN. 1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ testb(rax, Immediate(5)); 1823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(zero, &valid_result); 1833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp(0); // Drop result in st(0). 1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int64_t kNaNValue = V8_INT64_C(0x7ff8000000000000); 1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rcx, kNaNValue, RelocInfo::NONE); 1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(Operand(rsp, kPointerSize), rcx); 1873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movsd(xmm0, Operand(rsp, kPointerSize)); 1883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ jmp(&return_result); 1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If result is valid, return that. 1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&valid_result); 1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp_d(Operand(rsp, kPointerSize)); 1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movsd(xmm0, Operand(rsp, kPointerSize)); 1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Clean up FPU stack and exceptions and return xmm0 1963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&return_result); 1973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp(0); // Unload y. 1983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label clear_exceptions; 2003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ testb(rax, Immediate(0x3f /* Any Exception*/)); 2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &clear_exceptions); 2023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 2033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&clear_exceptions); 2043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fnclex(); 2053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 2063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CodeDesc desc; 2083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block masm.GetCode(&desc); 2093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch OS::ProtectCode(buffer, actual_size); 2108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Call the function from C++ through this pointer. 2113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return FUNCTION_CAST<ModuloFunction>(buffer); 2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 2133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef __ 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// ------------------------------------------------------------------------- 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Code generators 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define __ ACCESS_MASM(masm) 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ElementsTransitionGenerator::GenerateSmiOnlyToObject( 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm) { 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------- S t a t e ------------- 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rax : value 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rbx : target map 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rcx : key 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rdx : receiver 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rsp[0] : return address 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------------------------------- 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set transitioned map. 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rdx, 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HeapObject::kMapOffset, 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rbx, 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rdi, 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ElementsTransitionGenerator::GenerateSmiOnlyToDouble( 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, Label* fail) { 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------- S t a t e ------------- 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rax : value 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rbx : target map 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rcx : key 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rdx : receiver 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rsp[0] : return address 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------------------------------- 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The fail label is not actually used since we do not allocate. 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label allocated, new_backing_store, only_change_map, done; 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for empty arrays, which only require a map transition and no changes 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // to the backing store. 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(r8, Heap::kEmptyFixedArrayRootIndex); 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &only_change_map); 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check backing store for COW-ness. For COW arrays we have to 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocate a new backing store. 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(r8, HeapObject::kMapOffset), 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedCOWArrayMapRootIndex); 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &new_backing_store); 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the backing store is in new-space. If not, we need to allocate 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a new one since the old one is in pointer-space. 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If in new space, we can reuse the old backing store because it is 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the same size. 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotInNewSpace(r8, rdi, &new_backing_store); 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(r14, r8); // Destination array equals source array. 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r8 : source FixedArray 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r9 : elements array length 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r14: destination FixedDoubleArray 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set backing store's map 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(r14, HeapObject::kMapOffset), rdi); 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&allocated); 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set transitioned map. 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rdx, 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HeapObject::kMapOffset, 2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rbx, 2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rdi, 2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Convert smis to doubles and holes to hole NaNs. The Array's length 2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // remains unchanged. 2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FixedDoubleArray::kLengthOffset == FixedArray::kLengthOffset); 2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); 2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry, convert_hole; 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(r15, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE); 3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r15: the-hole NaN 3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&entry); 3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate new backing store. 3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&new_backing_store); 3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize)); 3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(rdi, r14, r11, r15, fail, TAG_OBJECT); 3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set backing store's map 3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); 3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(r14, HeapObject::kMapOffset), rdi); 3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set receiver's backing store. 3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdx, JSObject::kElementsOffset), r14); 3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(r11, r14); 3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rdx, 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSObject::kElementsOffset, 3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r11, 3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r15, 3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set backing store's length. 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Integer32ToSmi(r11, r9); 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(r14, FixedDoubleArray::kLengthOffset), r11); 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&allocated); 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&only_change_map); 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set transitioned map. 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rdx, 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HeapObject::kMapOffset, 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rbx, 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rdi, 3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_REMEMBERED_SET, 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Conversion loop. 3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(r8, r9, times_8, FixedArray::kHeaderSize)); 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r9 : current element's index 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rbx: current element (smi-tagged) 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(rbx, &convert_hole); 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(rbx, rbx); 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cvtlsi2sd(xmm0, rbx); 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize), 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xmm0); 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&entry); 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&convert_hole); 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "object found in smi-only array"); 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize), r15); 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ decq(r9); 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_sign, &loop); 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ElementsTransitionGenerator::GenerateDoubleToObject( 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, Label* fail) { 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------- S t a t e ------------- 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rax : value 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rbx : target map 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rcx : key 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rdx : receiver 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- rsp[0] : return address 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------------------------------- 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry, convert_hole, gc_required, only_change_map; 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for empty arrays, which only require a map transition and no changes 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // to the backing store. 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(r8, Heap::kEmptyFixedArrayRootIndex); 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &only_change_map); 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(rax); 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r8 : source FixedDoubleArray 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r9 : number of elements 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize)); 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(rdi, r11, r14, r15, &gc_required, TAG_OBJECT); 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r11: destination FixedArray 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex); 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(r11, HeapObject::kMapOffset), rdi); 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Integer32ToSmi(r14, r9); 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(r11, FixedArray::kLengthOffset), r14); 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Prepare for conversion loop. 3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE); 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rdi, Heap::kTheHoleValueRootIndex); 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rsi: the-hole NaN 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: pointer to the-hole 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&entry); 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call into runtime if GC is required. 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&gc_required); 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(rax); 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(fail); 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Box doubles into heap numbers. 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(r14, FieldOperand(r8, 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r9, 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_pointer_size, 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedDoubleArray::kHeaderSize)); 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r9 : current element's index 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r14: current element 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(r14, rsi); 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &convert_hole); 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Non-hole double, copy value into a heap number. 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateHeapNumber(rax, r15, &gc_required); 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax: new heap number 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rax, HeapNumber::kValueOffset), r14); 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(r11, 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r9, 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_pointer_size, 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize), 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax); 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(r15, r9); 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteArray(r11, 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r15, 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&entry, Label::kNear); 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Replace the-hole NaN with the-hole pointer. 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&convert_hole); 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(r11, 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r9, 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_pointer_size, 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize), 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rdi); 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ decq(r9); 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_sign, &loop); 4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Replace receiver's backing store with newly created and filled FixedArray. 4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdx, JSObject::kElementsOffset), r11); 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rdx, 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSObject::kElementsOffset, 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r11, 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r15, 4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(rax); 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&only_change_map); 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set transitioned map. 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rdx, 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HeapObject::kMapOffset, 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rbx, 4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rdi, 4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_REMEMBERED_SET, 4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StringCharLoadGenerator::Generate(MacroAssembler* masm, 4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register string, 4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index, 4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result, 4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* call_runtime) { 4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fetch the instance type of the receiver into result register. 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); 4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); 4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We need special handling for indirect strings. 4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label check_sequential; 4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(result, Immediate(kIsIndirectStringMask)); 4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(zero, &check_sequential, Label::kNear); 4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Dispatch on the indirect string shape: slice or cons. 4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label cons_string; 4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(result, Immediate(kSlicedNotConsMask)); 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(zero, &cons_string, Label::kNear); 4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle slices. 4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label indirect_string_loaded; 4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(result, FieldOperand(string, SlicedString::kOffsetOffset)); 4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addq(index, result); 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(string, FieldOperand(string, SlicedString::kParentOffset)); 5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&indirect_string_loaded, Label::kNear); 5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle cons strings. 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check whether the right hand side is the empty string (i.e. if 5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // this is really a flat string in a cons string). If that is not 5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the case we would rather go to the runtime system now to flatten 5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the string. 5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&cons_string); 5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset), 5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kEmptyStringRootIndex); 5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, call_runtime); 5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(string, FieldOperand(string, ConsString::kFirstOffset)); 5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&indirect_string_loaded); 5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); 5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); 5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Distinguish sequential and external strings. Only these two string 5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // representations can reach here (slices and flat cons strings have been 5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // reduced to the underlying sequential or external string). 5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label seq_string; 5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_sequential); 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSeqStringTag == 0); 5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(result, Immediate(kStringRepresentationMask)); 5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(zero, &seq_string, Label::kNear); 5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle external strings. 5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ascii_external, done; 5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert that we do not have a cons or slice (indirect strings) here. 5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sequential strings have already been ruled out. 5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(result, Immediate(kIsIndirectStringMask)); 5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(zero, "external string expected, but not found"); 5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Rule out short external strings. 5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_CHECK(kShortExternalStringTag != 0); 5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(result, Immediate(kShortExternalStringTag)); 5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_zero, call_runtime); 5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check encoding. 5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kTwoByteStringTag == 0); 5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(result, Immediate(kStringEncodingMask)); 5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(result, FieldOperand(string, ExternalString::kResourceDataOffset)); 5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &ascii_external, Label::kNear); 5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Two-byte string. 5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzxwl(result, Operand(result, index, times_2, 0)); 5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done, Label::kNear); 5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&ascii_external); 5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Ascii string. 5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzxbl(result, Operand(result, index, times_1, 0)); 5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done, Label::kNear); 5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Dispatch on the encoding: ASCII or two-byte. 5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ascii; 5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&seq_string); 5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); 5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(result, Immediate(kStringEncodingMask)); 5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_zero, &ascii, Label::kNear); 5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Two-byte string. 5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the two-byte character code into the result register. 5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzxwl(result, FieldOperand(string, 5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_2, 5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SeqTwoByteString::kHeaderSize)); 5663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done, Label::kNear); 5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ASCII string. 5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the byte into the result register. 5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&ascii); 5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzxbl(result, FieldOperand(string, 5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_1, 5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SeqAsciiString::kHeaderSize)); 5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 583