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