13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Redistribution and use in source and binary forms, with or without 344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// modification, are permitted provided that the following conditions are 444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// met: 544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// 644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// * Redistributions of source code must retain the above copyright 744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// notice, this list of conditions and the following disclaimer. 844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// * Redistributions in binary form must reproduce the above 944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// copyright notice, this list of conditions and the following 1044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// disclaimer in the documentation and/or other materials provided 1144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// with the distribution. 1244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// * Neither the name of Google Inc. nor the names of its 1344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// contributors may be used to endorse or promote products derived 1444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// from this software without specific prior written permission. 1544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// 1644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "v8.h" 2944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#if defined(V8_TARGET_ARCH_MIPS) 3144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "bootstrapper.h" 3344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "code-stubs.h" 34257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "codegen.h" 3544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "regexp-macro-assembler.h" 3644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3744f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace v8 { 3844f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace internal { 3944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define __ ACCESS_MASM(masm) 4244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, 44257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* slow, 45257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition cc, 46257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool never_nan_nan); 47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, 48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register lhs, 49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rhs, 50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* rhs_not_nan, 51257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* slow, 52257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool strict); 53257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc); 54257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, 55257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register lhs, 56257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rhs); 57257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 58257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 59257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Check if the operand is a heap number. 60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EmitCheckForHeapNumber(MacroAssembler* masm, Register operand, 61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, Register scratch2, 62257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* not_a_heap_number) { 63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, FieldMemOperand(operand, HeapObject::kMapOffset)); 64257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(scratch2, Heap::kHeapNumberMapRootIndex); 65257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_a_heap_number, ne, scratch1, Operand(scratch2)); 66257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid ToNumberStub::Generate(MacroAssembler* masm) { 70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The ToNumber stub takes one argument in a0. 71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label check_heap_number, call_builtin; 72257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(a0, &check_heap_number); 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 74257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, a0); 75257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 76257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&check_heap_number); 77257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitCheckForHeapNumber(masm, a0, a1, t0, &call_builtin); 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 79257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, a0); 80257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_builtin); 82257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(a0); 83257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); 8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid FastNewClosureStub::Generate(MacroAssembler* masm) { 88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Create a new closure from the given function info in new 89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // space. Set the context to the current context in cp. 90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label gc; 91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Pop the function info from the stack. 93257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ pop(a3); 94257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Attempt to allocate new JSFunction in new space. 96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateInNewSpace(JSFunction::kSize, 97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch v0, 98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a1, 99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a2, 100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &gc, 101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TAG_OBJECT); 102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int map_index = (language_mode_ == CLASSIC_MODE) 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? Context::FUNCTION_MAP_INDEX 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : Context::STRICT_MODE_FUNCTION_MAP_INDEX; 106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute the function map in the current global context and set that 108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // as the map of the allocated object. 109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalContextOffset)); 111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, MemOperand(a2, Context::SlotOffset(map_index))); 112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); 113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Initialize the rest of the function. We don't have to update the 115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // write barrier because the allocated object is in new space. 116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(a1, Heap::kEmptyFixedArrayRootIndex); 117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(a2, Heap::kTheHoleValueRootIndex); 118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); 119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, FieldMemOperand(v0, JSObject::kPropertiesOffset)); 120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, FieldMemOperand(v0, JSObject::kElementsOffset)); 121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset)); 122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, FieldMemOperand(v0, JSFunction::kSharedFunctionInfoOffset)); 123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(cp, FieldMemOperand(v0, JSFunction::kContextOffset)); 124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, FieldMemOperand(v0, JSFunction::kLiteralsOffset)); 125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t0, FieldMemOperand(v0, JSFunction::kNextFunctionLinkOffset)); 126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Initialize the code pointer in the function to be the one 128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // found in the shared function info object. 129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a3, SharedFunctionInfo::kCodeOffset)); 130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a3, a3, Operand(Code::kHeaderSize - kHeapObjectTag)); 131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return result. The argument function info has been popped already. 1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a3, FieldMemOperand(v0, JSFunction::kCodeEntryOffset)); 134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Create a new closure through the slower runtime call. 137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&gc); 138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t0, Heap::kFalseValueRootIndex); 139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(cp, a3, t0); 140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallRuntime(Runtime::kNewClosure, 3, 1); 14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 14444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid FastNewContextStub::Generate(MacroAssembler* masm) { 145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Try to allocate the context in new space. 146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label gc; 147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int length = slots_ + Context::MIN_CONTEXT_SLOTS; 148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Attempt to allocate the context in new space. 150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateInNewSpace(FixedArray::SizeFor(length), 151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch v0, 152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a1, 153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a2, 154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &gc, 155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TAG_OBJECT); 156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the function from the stack. 158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, MemOperand(sp, 0)); 159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the object header. 1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(a1, Heap::kFunctionContextMapRootIndex); 162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a2, Operand(Smi::FromInt(length))); 163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, FieldMemOperand(v0, FixedArray::kLengthOffset)); 1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); 165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the fixed slots, copy the global object from the previous context. 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a1, Operand(Smi::FromInt(0))); 169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, MemOperand(v0, Context::SlotOffset(Context::CLOSURE_INDEX))); 1703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(cp, MemOperand(v0, Context::SlotOffset(Context::PREVIOUS_INDEX))); 171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, MemOperand(v0, Context::SlotOffset(Context::EXTENSION_INDEX))); 1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a2, MemOperand(v0, Context::SlotOffset(Context::GLOBAL_INDEX))); 173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Initialize the rest of the slots to undefined. 175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); 176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { 177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, MemOperand(v0, Context::SlotOffset(i))); 178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Remove the on-stack argument and return. 181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(cp, v0); 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(1); 183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Need to collect. Call into runtime system. 185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&gc); 1863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1); 18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 18844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FastNewBlockContextStub::Generate(MacroAssembler* masm) { 1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Stack layout on entry: 1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // [sp]: function. 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // [sp + kPointerSize]: serialized scope info 1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Try to allocate the context in new space. 1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label gc; 1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int length = slots_ + Context::MIN_CONTEXT_SLOTS; 1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(FixedArray::SizeFor(length), 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch v0, a1, a2, &gc, TAG_OBJECT); 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the function from the stack. 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, MemOperand(sp, 0)); 2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the serialized scope info from the stack. 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a1, MemOperand(sp, 1 * kPointerSize)); 2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the object header. 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(a2, Heap::kBlockContextMapRootIndex); 2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a2, Operand(Smi::FromInt(length))); 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a2, FieldMemOperand(v0, FixedArray::kLengthOffset)); 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If this block context is nested in the global context we get a smi 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sentinel instead of a function. The block context should get the 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // canonical empty function of the global context as its closure which 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // we still have to look up. 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label after_sentinel; 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(a3, &after_sentinel); 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const char* message = "Expected 0 as a Smi sentinel"; 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(eq, message, a3, Operand(zero_reg)); 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, GlobalObjectOperand()); 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, FieldMemOperand(a3, GlobalObject::kGlobalContextOffset)); 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, ContextOperand(a3, Context::CLOSURE_INDEX)); 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&after_sentinel); 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the fixed slots, copy the global object from the previous context. 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a2, ContextOperand(cp, Context::GLOBAL_INDEX)); 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a3, ContextOperand(v0, Context::CLOSURE_INDEX)); 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(cp, ContextOperand(v0, Context::PREVIOUS_INDEX)); 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a1, ContextOperand(v0, Context::EXTENSION_INDEX)); 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a2, ContextOperand(v0, Context::GLOBAL_INDEX)); 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the rest of the slots to the hole value. 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(a1, Heap::kTheHoleValueRootIndex); 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < slots_; i++) { 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a1, ContextOperand(v0, i + Context::MIN_CONTEXT_SLOTS)); 2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Remove the on-stack argument and return. 2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(cp, v0); 2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(2); 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Need to collect. Call into runtime system. 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&gc); 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1); 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateFastCloneShallowArrayCommon( 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int length, 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastCloneShallowArrayStub::Mode mode, 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail) { 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Registers on entry: 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a3: boilerplate literal array. 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(mode != FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS); 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // All sizes here are multiples of kPointerSize. 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int elements_size = 0; 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (length > 0) { 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_size = mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? FixedDoubleArray::SizeFor(length) 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : FixedArray::SizeFor(length); 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = JSArray::kSize + elements_size; 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate both the JS array and the elements array in one big 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocation. This avoids multiple limit checks. 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch v0, 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a1, 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a2, 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fail, 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TAG_OBJECT); 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy the JS array part. 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < JSArray::kSize; i += kPointerSize) { 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if ((i != JSArray::kElementsOffset) || (length == 0)) { 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a1, FieldMemOperand(a3, i)); 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a1, FieldMemOperand(v0, i)); 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (length > 0) { 2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get hold of the elements array of the boilerplate and setup the 2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements pointer in the resulting object. 2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, FieldMemOperand(a3, JSArray::kElementsOffset)); 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(a2, v0, Operand(JSArray::kSize)); 2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a2, FieldMemOperand(v0, JSArray::kElementsOffset)); 2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy the elements array. 2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT((elements_size % kPointerSize) == 0); 2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CopyFields(a2, a3, a1.bit(), elements_size / kPointerSize); 2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { 301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stack layout on entry: 3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // [sp]: constant elements. 304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // [sp + kPointerSize]: literal index. 305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // [sp + (2 * kPointerSize)]: literals array. 306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load boilerplate object into r3 and check if we need to create a 308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // boilerplate. 309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow_case; 310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, MemOperand(sp, 2 * kPointerSize)); 311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(sp, 1 * kPointerSize)); 312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize); 314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t0, a3, t0); 315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, MemOperand(t0)); 316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t1, Heap::kUndefinedValueRootIndex); 317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&slow_case, eq, a3, Operand(t1)); 318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastCloneShallowArrayStub::Mode mode = mode_; 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mode == CLONE_ANY_ELEMENTS) { 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label double_elements, check_fast_elements; 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(v0, FieldMemOperand(a3, JSArray::kElementsOffset)); 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset)); 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(t1, Heap::kFixedCOWArrayMapRootIndex); 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&check_fast_elements, ne, v0, Operand(t1)); 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastCloneShallowArrayCommon(masm, 0, 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch COPY_ON_WRITE_ELEMENTS, &slow_case); 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Return and remove the on-stack parameters. 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(3); 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_fast_elements); 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(t1, Heap::kFixedArrayMapRootIndex); 3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&double_elements, ne, v0, Operand(t1)); 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastCloneShallowArrayCommon(masm, length_, 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CLONE_ELEMENTS, &slow_case); 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Return and remove the on-stack parameters. 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(3); 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&double_elements); 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode = CLONE_DOUBLE_ELEMENTS; 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fall through to generate the code to handle double elements. 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (FLAG_debug_code) { 345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const char* message; 346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap::RootListIndex expected_map_index; 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mode == CLONE_ELEMENTS) { 348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch message = "Expected (writable) fixed array"; 349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch expected_map_index = Heap::kFixedArrayMapRootIndex; 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (mode == CLONE_DOUBLE_ELEMENTS) { 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch message = "Expected (writable) fixed double array"; 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expected_map_index = Heap::kFixedDoubleArrayMapRootIndex; 353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(mode == COPY_ON_WRITE_ELEMENTS); 355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch message = "Expected copy-on-write fixed array"; 356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch expected_map_index = Heap::kFixedCOWArrayMapRootIndex; 357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(a3); 359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a3, JSArray::kElementsOffset)); 360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a3, HeapObject::kMapOffset)); 361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(at, expected_map_index); 362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Assert(eq, message, a3, Operand(at)); 363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ pop(a3); 364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastCloneShallowArrayCommon(masm, length_, mode, &slow_case); 367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Return and remove the on-stack parameters. 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(3); 370592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow_case); 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 374592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FastCloneShallowObjectStub::Generate(MacroAssembler* masm) { 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Stack layout on entry: 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // [sp]: object literal flags. 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // [sp + kPointerSize]: constant properties. 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // [sp + (2 * kPointerSize)]: literal index. 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // [sp + (3 * kPointerSize)]: literals array. 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load boilerplate object into a3 and check if we need to create a 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // boilerplate. 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label slow_case; 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, MemOperand(sp, 3 * kPointerSize)); 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a0, MemOperand(sp, 2 * kPointerSize)); 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize); 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(a3, t0, a3); 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, MemOperand(a3)); 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&slow_case, eq, a3, Operand(t0)); 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the boilerplate contains only fast properties and we can 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // statically determine the instance size. 3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = JSObject::kHeaderSize + length_ * kPointerSize; 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a0, FieldMemOperand(a3, HeapObject::kMapOffset)); 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lbu(a0, FieldMemOperand(a0, Map::kInstanceSizeOffset)); 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&slow_case, ne, a0, Operand(size >> kPointerSizeLog2)); 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate the JS object and copy header together with all in-object 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // properties from the boilerplate. 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, v0, a1, a2, &slow_case, TAG_OBJECT); 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < size; i += kPointerSize) { 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a1, FieldMemOperand(a3, i)); 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a1, FieldMemOperand(v0, i)); 409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return and remove the on-stack parameters. 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(4); 413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow_case); 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallRuntime(Runtime::kCreateObjectLiteralShallow, 4, 1); 41644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 41744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 41844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 41944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Takes a Smi and converts to an IEEE 64 bit floating point value in two 42044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// registers. The format is 1 sign bit, 11 exponent bits (biased 1023) and 42144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// 52 fraction bits (20 in the first word, 32 in the second). Zeros is a 42244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// scratch register. Destroys the source register. No GC occurs during this 42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// stub so you don't have to set up the frame. 42444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass ConvertToDoubleStub : public CodeStub { 42544f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 42644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ConvertToDoubleStub(Register result_reg_1, 42744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result_reg_2, 42844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register source_reg, 42944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch_reg) 43044f0eee88ff00398ff7f715fab053374d808c90dSteve Block : result1_(result_reg_1), 43144f0eee88ff00398ff7f715fab053374d808c90dSteve Block result2_(result_reg_2), 43244f0eee88ff00398ff7f715fab053374d808c90dSteve Block source_(source_reg), 43344f0eee88ff00398ff7f715fab053374d808c90dSteve Block zeros_(scratch_reg) { } 43444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 43644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result1_; 43744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result2_; 43844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register source_; 43944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register zeros_; 44044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 44144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Minor key encoding in 16 bits. 44244f0eee88ff00398ff7f715fab053374d808c90dSteve Block class ModeBits: public BitField<OverwriteMode, 0, 2> {}; 44344f0eee88ff00398ff7f715fab053374d808c90dSteve Block class OpBits: public BitField<Token::Value, 2, 14> {}; 44444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 44544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Major MajorKey() { return ConvertToDouble; } 44644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int MinorKey() { 44744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Encode the parameters in a unique 16 bit value. 44844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return result1_.code() + 44944f0eee88ff00398ff7f715fab053374d808c90dSteve Block (result2_.code() << 4) + 45044f0eee88ff00398ff7f715fab053374d808c90dSteve Block (source_.code() << 8) + 45144f0eee88ff00398ff7f715fab053374d808c90dSteve Block (zeros_.code() << 12); 45244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 45344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 45444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Generate(MacroAssembler* masm); 45544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 45644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 45744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 45844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid ConvertToDoubleStub::Generate(MacroAssembler* masm) { 459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifndef BIG_ENDIAN_FLOATING_POINT 460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register exponent = result1_; 461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register mantissa = result2_; 462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else 463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register exponent = result2_; 464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register mantissa = result1_; 465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_special; 467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert from Smi to integer. 468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(source_, source_, kSmiTagSize); 469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Move sign bit from source to destination. This works because the sign bit 470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // in the exponent word of the double has the same position and polarity as 471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the 2's complement sign bit in a Smi. 472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); 473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(exponent, source_, Operand(HeapNumber::kSignMask)); 474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Subtract from 0 if source was negative. 475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(at, zero_reg, source_); 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movn(source_, at, exponent); 477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We have -1, 0 or 1, which we treat specially. Register source_ contains 479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // absolute value: it is either equal to 1 (special case of -1 and 1), 480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // greater than 1 (not a special case) or less than 1 (special case of 0). 481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_special, gt, source_, Operand(1)); 482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For 1 or -1 we need to or in the 0 exponent (biased to 1023). 484db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const uint32_t exponent_word_for_1 = 485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HeapNumber::kExponentBias << HeapNumber::kExponentShift; 486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Safe to use 'at' as dest reg here. 487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(at, exponent, Operand(exponent_word_for_1)); 4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movn(exponent, at, source_); // Write exp when source not 0. 489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 1, 0 and -1 all have 0 for the second word. 4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(mantissa, zero_reg); 492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_special); 494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Count leading zeros. 495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Gets the wrong answer for 0, but we already checked for that case above. 4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Clz(zeros_, source_); 497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute exponent and or it into the exponent register. 498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We use mantissa as a scratch register here. 499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(mantissa, Operand(31 + HeapNumber::kExponentBias)); 500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(mantissa, mantissa, zeros_); 501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(mantissa, mantissa, HeapNumber::kExponentShift); 502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(exponent, exponent, mantissa); 503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Shift up the source chopping the top bit off. 505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(zeros_, zeros_, Operand(1)); 506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0. 507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(source_, source_, zeros_); 508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute lower part of fraction (last 12 bits). 509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(mantissa, source_, HeapNumber::kMantissaBitsInTopWord); 510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // And the top (top 20 bits). 511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(source_, source_, 32 - HeapNumber::kMantissaBitsInTopWord); 51285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(exponent, exponent, source_); 51544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 51844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid FloatingPointHelper::LoadSmis(MacroAssembler* masm, 51944f0eee88ff00398ff7f715fab053374d808c90dSteve Block FloatingPointHelper::Destination destination, 52044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 52144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2) { 522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(scratch1, a0, kSmiTagSize); 525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(scratch1, f14); 526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_w(f14, f14); 527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(scratch1, a1, kSmiTagSize); 528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(scratch1, f12); 529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_w(f12, f12); 530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (destination == kCoreRegisters) { 531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(a2, a3, f14); 532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(a0, a1, f12); 533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(destination == kCoreRegisters); 536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Write Smi from a0 to a3 and a2 in double format. 537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(scratch1, a0); 538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ConvertToDoubleStub stub1(a3, a2, scratch1, scratch2); 539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ra); 5403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Call(stub1.GetCode()); 541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Write Smi from a1 to a1 and a0 in double format. 542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(scratch1, a1); 543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ConvertToDoubleStub stub2(a1, a0, scratch1, scratch2); 5443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Call(stub2.GetCode()); 545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ pop(ra); 546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 54944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 55044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid FloatingPointHelper::LoadOperands( 55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block MacroAssembler* masm, 55244f0eee88ff00398ff7f715fab053374d808c90dSteve Block FloatingPointHelper::Destination destination, 55344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register heap_number_map, 55444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 55544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 55644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* slow) { 557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load right operand (a0) to f12 or a2/a3. 559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadNumber(masm, destination, 560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a0, f14, a2, a3, heap_number_map, scratch1, scratch2, slow); 561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load left operand (a1) to f14 or a0/a1. 563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadNumber(masm, destination, 564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a1, f12, a0, a1, heap_number_map, scratch1, scratch2, slow); 56544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 56644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 56744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 56844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid FloatingPointHelper::LoadNumber(MacroAssembler* masm, 56944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Destination destination, 57044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register object, 57144f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPURegister dst, 57244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register dst1, 57344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register dst2, 57444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register heap_number_map, 57544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 57644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 57744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* not_number) { 578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (FLAG_debug_code) { 579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AbortIfNotRootValue(heap_number_map, 580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap::kHeapNumberMapRootIndex, 581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "HeapNumberMap register clobbered."); 582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label is_smi, done; 585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Smi-check 5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ UntagAndJumpIfSmi(scratch1, object, &is_smi); 5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Heap number check 589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); 590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle loading a double from a heap number. 592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU) && 593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch destination == kFPURegisters) { 594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the double from tagged HeapNumber to double register. 596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ARM uses a workaround here because of the unaligned HeapNumber 598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // kValueOffset. On MIPS this workaround is built into ldc1 so there's no 599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // point in generating even more instructions. 600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(dst, FieldMemOperand(object, HeapNumber::kValueOffset)); 601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(destination == kCoreRegisters); 603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the double from heap number to dst1 and dst2 in double format. 604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(dst1, FieldMemOperand(object, HeapNumber::kValueOffset)); 605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(dst2, FieldMemOperand(object, 606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HeapNumber::kValueOffset + kPointerSize)); 607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done); 609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle loading a double from a smi. 611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&is_smi); 612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert smi to double using FPU instructions. 615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(scratch1, dst); 616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_w(dst, dst); 617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (destination == kCoreRegisters) { 618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the converted smi to dst1 and dst2 in double format. 619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(dst1, dst2, dst); 620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(destination == kCoreRegisters); 623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Write smi to dst1 and dst2 double format. 624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(scratch1, object); 625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ConvertToDoubleStub stub(dst2, dst1, scratch1, scratch2); 626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ra); 6273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Call(stub.GetCode()); 628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ pop(ra); 629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 63244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 63344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 63444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm, 636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register object, 637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst, 638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register heap_number_map, 639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2, 641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch3, 642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FPURegister double_scratch, 643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* not_number) { 644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (FLAG_debug_code) { 645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AbortIfNotRootValue(heap_number_map, 646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap::kHeapNumberMapRootIndex, 647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "HeapNumberMap register clobbered."); 648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_in_int32_range; 651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ UntagAndJumpIfSmi(dst, object, &done); 653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset)); 654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_number, ne, scratch1, Operand(heap_number_map)); 655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ConvertToInt32(object, 656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dst, 657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch double_scratch, 660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ¬_in_int32_range); 661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done); 662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_in_int32_range); 664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset)); 665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset)); 666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ EmitOutOfInt32RangeTruncate(dst, 668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch3); 671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm, 677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register int_scratch, 678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Destination destination, 679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FPURegister double_dst, 680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst1, 681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst2, 682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2, 683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FPURegister single_scratch) { 684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!int_scratch.is(scratch2)); 685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!int_scratch.is(dst1)); 686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!int_scratch.is(dst2)); 687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(int_scratch, single_scratch); 693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_w(double_dst, single_scratch); 694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (destination == kCoreRegisters) { 695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(dst1, dst2, double_dst); 696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label fewer_than_20_useful_bits; 699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Expected output: 700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // | dst2 | dst1 | 701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // | s | exp | mantissa | 702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for zero. 704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(dst2, int_scratch); 705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(dst1, int_scratch); 706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, eq, int_scratch, Operand(zero_reg)); 707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Preload the sign of the value. 709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(dst2, int_scratch, Operand(HeapNumber::kSignMask)); 710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the absolute value of the object (as an unsigned integer). 711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip_sub; 712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&skip_sub, ge, dst2, Operand(zero_reg)); 713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(int_scratch, zero_reg, int_scratch); 714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&skip_sub); 715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get mantissa[51:20]. 717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the position of the first set bit. 7193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Clz(dst1, int_scratch); 720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(scratch2, 31); 721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(dst1, scratch2, dst1); 722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set the exponent. 724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch2, dst1, Operand(HeapNumber::kExponentBias)); 725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ins(dst2, scratch2, 726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HeapNumber::kExponentShift, HeapNumber::kExponentBits); 727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Clear the first non null bit. 729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(scratch2, Operand(1)); 730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(scratch2, scratch2, dst1); 731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(at, -1); 732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(scratch2, scratch2, at); 733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(int_scratch, int_scratch, scratch2); 734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the number of bits to set in the lower part of the mantissa. 736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(scratch2, dst1, Operand(HeapNumber::kMantissaBitsInTopWord)); 737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&fewer_than_20_useful_bits, lt, scratch2, Operand(zero_reg)); 738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set the higher 20 bits of the mantissa. 739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srlv(at, int_scratch, scratch2); 740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(dst2, dst2, at); 741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(at, 32); 742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(scratch2, at, scratch2); 743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(dst1, int_scratch, scratch2); 744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done); 745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&fewer_than_20_useful_bits); 747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(at, HeapNumber::kMantissaBitsInTopWord); 748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(scratch2, at, dst1); 749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(scratch2, int_scratch, scratch2); 750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(dst2, dst2, scratch2); 751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set dst1 to 0. 752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(dst1, zero_reg); 753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, 759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register object, 760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Destination destination, 7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoubleRegister double_dst, 762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst1, 763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst2, 764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register heap_number_map, 765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2, 767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FPURegister single_scratch, 768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* not_int32) { 769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!scratch1.is(object) && !scratch2.is(object)); 770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!scratch1.is(scratch2)); 771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!heap_number_map.is(object) && 772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch !heap_number_map.is(scratch1) && 773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch !heap_number_map.is(scratch2)); 774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, obj_is_not_smi; 776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(object, &obj_is_not_smi); 778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(scratch1, object); 779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ConvertIntToDouble(masm, scratch1, destination, double_dst, dst1, dst2, 780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, single_scratch); 781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done); 782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&obj_is_not_smi); 784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (FLAG_debug_code) { 785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AbortIfNotRootValue(heap_number_map, 786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap::kHeapNumberMapRootIndex, 787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "HeapNumberMap register clobbered."); 788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); 790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the number. 792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the double value. 795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset)); 796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register except_flag = scratch2; 7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ EmitFPUTruncate(kRoundToZero, 7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch single_scratch, 8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch double_dst, 8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, 8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch except_flag, 8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kCheckForInexactConversion); 804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Jump to not_int32 if the operation did not succeed. 8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(not_int32, ne, except_flag, Operand(zero_reg)); 807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (destination == kCoreRegisters) { 809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(dst1, dst2, double_dst); 810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!scratch1.is(object) && !scratch2.is(object)); 814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the double value in the destination registers. 815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(dst2, FieldMemOperand(object, HeapNumber::kExponentOffset)); 816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(dst1, FieldMemOperand(object, HeapNumber::kMantissaOffset)); 817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for 0 and -0. 819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch1, dst1, Operand(~HeapNumber::kSignMask)); 820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(scratch1, scratch1, Operand(dst2)); 821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, eq, scratch1, Operand(zero_reg)); 822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the value can be exactly represented by a 32-bit integer. 824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Jump to not_int32 if that's not the case. 825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DoubleIs32BitInteger(masm, dst1, dst2, scratch1, scratch2, not_int32); 826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // dst1 and dst2 were trashed. Reload the double value. 828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(dst2, FieldMemOperand(object, HeapNumber::kExponentOffset)); 829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(dst1, FieldMemOperand(object, HeapNumber::kMantissaOffset)); 830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, 837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register object, 838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst, 839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register heap_number_map, 840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2, 842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch3, 8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoubleRegister double_scratch, 844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* not_int32) { 845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!dst.is(object)); 846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object)); 847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!scratch1.is(scratch2) && 848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch !scratch1.is(scratch3) && 849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch !scratch2.is(scratch3)); 850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ UntagAndJumpIfSmi(dst, object, &done); 854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (FLAG_debug_code) { 856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AbortIfNotRootValue(heap_number_map, 857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap::kHeapNumberMapRootIndex, 858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "HeapNumberMap register clobbered."); 859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); 861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Object is a heap number. 863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert the floating point value to a 32-bit integer. 864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the double value. 867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(double_scratch, FieldMemOperand(object, HeapNumber::kValueOffset)); 868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FPURegister single_scratch = double_scratch.low(); 8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register except_flag = scratch2; 8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ EmitFPUTruncate(kRoundToZero, 8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch single_scratch, 8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch double_scratch, 8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, 8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch except_flag, 8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kCheckForInexactConversion); 877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Jump to not_int32 if the operation did not succeed. 8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(not_int32, ne, except_flag, Operand(zero_reg)); 880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the result in the destination register. 8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mfc1(dst, single_scratch); 882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the double value in the destination registers. 885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch2, FieldMemOperand(object, HeapNumber::kExponentOffset)); 886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, FieldMemOperand(object, HeapNumber::kMantissaOffset)); 887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for 0 and -0. 889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(dst, scratch1, Operand(~HeapNumber::kSignMask)); 890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(dst, scratch2, Operand(dst)); 891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, eq, dst, Operand(zero_reg)); 892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DoubleIs32BitInteger(masm, scratch1, scratch2, dst, scratch3, not_int32); 894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers state after DoubleIs32BitInteger. 896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // dst: mantissa[51:20]. 897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // scratch2: 1 898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Shift back the higher bits of the mantissa. 900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srlv(dst, dst, scratch3); 901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set the implicit first bit. 902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(at, 32); 903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(scratch3, at, scratch3); 904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(scratch2, scratch2, scratch3); 905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(dst, dst, scratch2); 906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set the sign. 907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset)); 908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); 909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip_sub; 910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&skip_sub, ge, scratch1, Operand(zero_reg)); 911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(dst, zero_reg, dst); 912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&skip_sub); 913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FloatingPointHelper::DoubleIs32BitInteger(MacroAssembler* masm, 920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src1, 921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register src2, 922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst, 923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch, 924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* not_int32) { 925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get exponent alone in scratch. 926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ext(scratch, 927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch src1, 928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HeapNumber::kExponentShift, 929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HeapNumber::kExponentBits); 930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Substract the bias from the exponent. 932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(scratch, scratch, Operand(HeapNumber::kExponentBias)); 933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // src1: higher (exponent) part of the double value. 935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // src2: lower (mantissa) part of the double value. 936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // scratch: unbiased exponent. 937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fast cases. Check for obvious non 32-bit integer values. 939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Negative exponent cannot yield 32-bit integers. 940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_int32, lt, scratch, Operand(zero_reg)); 941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Exponent greater than 31 cannot yield 32-bit integers. 942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Also, a positive value with an exponent equal to 31 is outside of the 943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // signed 32-bit integer range. 944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Another way to put it is that if (exponent - signbit) > 30 then the 945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // number cannot be represented as an int32. 946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp = dst; 947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(at, src1, 31); 948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(tmp, scratch, at); 949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_int32, gt, tmp, Operand(30)); 950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // - Bits [21:0] in the mantissa are not null. 951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(tmp, src2, 0x3fffff); 952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_int32, ne, tmp, Operand(zero_reg)); 953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Otherwise the exponent needs to be big enough to shift left all the 955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // non zero bits left. So we need the (30 - exponent) last bits of the 956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 31 higher bits of the mantissa to be null. 957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Because bits [21:0] are null, we can check instead that the 9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // (32 - exponent) last bits of the 32 higher bits of the mantissa are null. 959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the 32 higher bits of the mantissa in dst. 961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ext(dst, 962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch src2, 963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HeapNumber::kMantissaBitsInTopWord, 964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32 - HeapNumber::kMantissaBitsInTopWord); 965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(at, src1, HeapNumber::kNonMantissaBitsInTopWord); 966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(dst, dst, at); 967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Create the mask and test the lower bits (of the higher bits). 969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(at, 32); 970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(scratch, at, scratch); 971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(src2, 1); 972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(src1, src2, scratch); 973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(src1, src1, Operand(1)); 974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(src1, dst, src1); 975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_int32, ne, src1, Operand(zero_reg)); 976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FloatingPointHelper::CallCCodeForDoubleOperation( 980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Token::Value op, 982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register heap_number_result, 983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch) { 984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Using core registers: 985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: Left value (least significant part of mantissa). 986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: Left value (sign, exponent, top of mantissa). 987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: Right value (least significant part of mantissa). 988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: Right value (sign, exponent, top of mantissa). 989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Assert that heap_number_result is saved. 991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We currently always use s0 to pass it. 992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(heap_number_result.is(s0)); 993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Push the current return address before the C call. 995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ra); 996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ PrepareCallCFunction(4, scratch); // Two doubles are 4 arguments. 997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!IsMipsSoftFloatABI) { 998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We are not using MIPS FPU instructions, and parameters for the runtime 1000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // function call are prepaired in a0-a3 registers, but function we are 1001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // calling is compiled with hard-float flag and expecting hard float ABI 1002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // (parameters in f12/f14 registers). We need to copy parameters from 1003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0-a3 registers to f12/f14 register pairs. 1004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(f12, a0, a1); 1005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(f14, a2, a3); 1006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction( 10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2); 10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Store answer in the overwritable heap number. 1013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!IsMipsSoftFloatABI) { 1014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 1015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Double returned in register f0. 1016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); 1017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Double returned in registers v0 and v1. 1019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(v1, FieldMemOperand(heap_number_result, HeapNumber::kExponentOffset)); 1020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(v0, FieldMemOperand(heap_number_result, HeapNumber::kMantissaOffset)); 1021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Place heap_number_result in v0 and return to the pushed return address. 102385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ pop(ra); 10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(v0, heap_number_result); 10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool WriteInt32ToHeapNumberStub::IsPregenerated() { 10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // These variants are compiled ahead of time. See next method. 10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (the_int_.is(a1) && 10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch the_heap_number_.is(v0) && 10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch_.is(a2) && 10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sign_.is(a3)) { 10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (the_int_.is(a2) && 10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch the_heap_number_.is(v0) && 10393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch_.is(a3) && 10403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sign_.is(a0)) { 10413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 10433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Other register combinations are generated as and when they are needed, 10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // so it is unsafe to call them from stubs (we can't generate a stub while 10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // we are generating a stub). 10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime() { 10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch WriteInt32ToHeapNumberStub stub1(a1, v0, a2, a3); 10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch WriteInt32ToHeapNumberStub stub2(a2, v0, a3, a0); 10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub1.GetCode()->set_is_pregenerated(true); 10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub2.GetCode()->set_is_pregenerated(true); 1055592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 1056592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1057592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 105844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// See comment for class, this does NOT work for int32's that are in Smi range. 105944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { 1060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label max_negative_int; 1061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the_int_ has the answer which is a signed int32 but not a Smi. 1062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We test for the special value that has a different exponent. 1063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); 1064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Test sign, and save for later conditionals. 1065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(sign_, the_int_, Operand(0x80000000u)); 1066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&max_negative_int, eq, the_int_, Operand(0x80000000u)); 1067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set up the correct exponent in scratch_. All non-Smi int32s have the same. 1069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). 1070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t non_smi_exponent = 1071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; 1072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(scratch_, Operand(non_smi_exponent)); 1073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set the sign bit in scratch_ if the value was negative. 1074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(scratch_, scratch_, sign_); 1075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Subtract from 0 if the value was negative. 1076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(at, zero_reg, the_int_); 10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movn(the_int_, at, sign_); 1078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We should be masking the implict first digit of the mantissa away here, 1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // but it just ends up combining harmlessly with the last digit of the 1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get 1081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the most significant 1 to hit the last bit of the 12 bit sign and exponent. 1082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); 1083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; 1084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(at, the_int_, shift_distance); 1085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(scratch_, scratch_, at); 1086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(scratch_, FieldMemOperand(the_heap_number_, 1087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HeapNumber::kExponentOffset)); 1088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(scratch_, the_int_, 32 - shift_distance); 1089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(scratch_, FieldMemOperand(the_heap_number_, 1090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HeapNumber::kMantissaOffset)); 1091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&max_negative_int); 1094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The max negative int32 is stored as a positive number in the mantissa of 1095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a double because it uses a sign bit instead of using two's complement. 1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The actual mantissa bits stored are all 0 because the implicit most 1097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // significant 1 bit is not stored. 1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch non_smi_exponent += 1 << HeapNumber::kExponentShift; 1099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(scratch_, Operand(HeapNumber::kSignMask | non_smi_exponent)); 1100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(scratch_, 1101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset)); 1102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(scratch_, zero_reg); 1103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(scratch_, 1104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); 1105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Handle the case where the lhs and rhs are the same object. 1110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Equality is almost reflexive (everything but NaN), so this is a test 1111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// for "identity and not NaN". 1112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, 1113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* slow, 1114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition cc, 1115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool never_nan_nan) { 1116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_identical; 1117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label heap_number, return_equal; 1118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register exp_mask_reg = t5; 1119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_identical, ne, a0, Operand(a1)); 1121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The two objects are identical. If we know that one of them isn't NaN then 1123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // we now know they test equal. 1124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc != eq || !never_nan_nan) { 1125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(exp_mask_reg, Operand(HeapNumber::kExponentMask)); 1126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Test for NaN. Sadly, we can't just compare to factory->nan_value(), 1128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // so we do the second best thing - test it ourselves. 1129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // They are both equal and they are not both Smis so both of them are not 1130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Smis. If it's not a heap number, then return equal. 1131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc == less || cc == greater) { 1132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a0, t4, t4); 11333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(slow, greater, t4, Operand(FIRST_SPEC_OBJECT_TYPE)); 1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a0, t4, t4); 1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&heap_number, eq, t4, Operand(HEAP_NUMBER_TYPE)); 1137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Comparing JS objects with <=, >= is complicated. 1138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc != eq) { 11393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(slow, greater, t4, Operand(FIRST_SPEC_OBJECT_TYPE)); 1140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Normally here we fall through to return_equal, but undefined is 1141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // special: (undefined == undefined) == true, but 1142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // (undefined <= undefined) == false! See ECMAScript 11.8.5. 1143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc == less_equal || cc == greater_equal) { 1144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_equal, ne, t4, Operand(ODDBALL_TYPE)); 1145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); 1146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_equal, ne, a0, Operand(t2)); 1147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc == le) { 1148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // undefined <= undefined should fail. 1149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(GREATER)); 1150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // undefined >= undefined should fail. 1152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(LESS)); 1153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&return_equal); 11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc == less) { 1163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(GREATER)); // Things aren't less than themselves. 1164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (cc == greater) { 1165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(LESS)); // Things aren't greater than themselves. 1166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, zero_reg); // Things are <=, >=, ==, === themselves. 1168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc != eq || !never_nan_nan) { 1172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For less and greater we don't have to check for NaN since the result of 1173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // x < x is false regardless. For the others here is some code to check 1174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // for NaN. 1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc != lt && cc != gt) { 1176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&heap_number); 1177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // It is a heap number, so return non-equal if it's NaN and equal if it's 1178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // not NaN. 1179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The representation of NaN values has all exponent bits (52..62) set, 1181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // and not all mantissa bits (0..51) clear. 1182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Read top bits of double representation (second word of value). 1183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t2, FieldMemOperand(a0, HeapNumber::kExponentOffset)); 1184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Test that exponent bits are all set. 1185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t3, t2, Operand(exp_mask_reg)); 1186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If all bits not set (ne cond), then not a NaN, objects are equal. 1187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_equal, ne, t3, Operand(exp_mask_reg)); 1188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Shift out flag and all exponent bits, retaining only mantissa. 1190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t2, t2, HeapNumber::kNonMantissaBitsInTopWord); 1191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Or with all low-bits of mantissa. 1192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t3, FieldMemOperand(a0, HeapNumber::kMantissaOffset)); 1193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(v0, t3, Operand(t2)); 1194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For equal we already have the right value in v0: Return zero (equal) 1195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // if all bits in mantissa are zero (it's an Infinity) and non-zero if 1196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // not (it's a NaN). For <= and >= we need to load v0 with the failing 1197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // value if it's a NaN. 1198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc != eq) { 1199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // All-zero means Infinity means equal. 1200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(eq, v0, Operand(zero_reg)); 1201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc == le) { 1202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(GREATER)); // NaN <= NaN should fail. 1203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(LESS)); // NaN >= NaN should fail. 1205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // No fall through here. 1210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_identical); 1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, 1217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register lhs, 1218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rhs, 1219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* both_loaded_as_doubles, 1220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* slow, 1221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool strict) { 1222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT((lhs.is(a0) && rhs.is(a1)) || 1223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (lhs.is(a1) && rhs.is(a0))); 1224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label lhs_is_smi; 12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(lhs, &lhs_is_smi); 1227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Rhs is a Smi. 1228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check whether the non-smi is a heap number. 1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(lhs, t4, t4); 1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (strict) { 1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If lhs was not a number and rhs was a Smi then strict equality cannot 1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // succeed. Return non-equal (lhs is already not zero). 12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT, ne, t4, Operand(HEAP_NUMBER_TYPE)); 1234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, lhs); 1235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Smi compared non-strictly with a non-Smi non-heap-number. Call 1237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the runtime. 1238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(slow, ne, t4, Operand(HEAP_NUMBER_TYPE)); 1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Rhs is a smi, lhs is a number. 1242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert smi rhs to double. 1243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 1244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 1245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(at, rhs, kSmiTagSize); 1246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(at, f14); 1247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_w(f14, f14); 1248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 1249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load lhs to a double in a2, a3. 1251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(lhs, HeapNumber::kValueOffset + 4)); 1252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 1253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Write Smi from rhs to a1 and a0 in double format. t5 is scratch. 1255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t6, rhs); 1256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ConvertToDoubleStub stub1(a1, a0, t6, t5); 1257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ra); 12583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Call(stub1.GetCode()); 1259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ pop(ra); 1261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We now have both loaded as doubles. 1264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(both_loaded_as_doubles); 1265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&lhs_is_smi); 1267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Lhs is a Smi. Check whether the non-smi is a heap number. 1268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(rhs, t4, t4); 1269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (strict) { 1270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If lhs was not a number and rhs was a Smi then strict equality cannot 1271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // succeed. Return non-equal. 12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT, ne, t4, Operand(HEAP_NUMBER_TYPE)); 1273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(1)); 1274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Smi compared non-strictly with a non-Smi non-heap-number. Call 1276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the runtime. 1277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(slow, ne, t4, Operand(HEAP_NUMBER_TYPE)); 1278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Lhs is a smi, rhs is a number. 1281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert smi lhs to double. 1282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 1283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 1284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(at, lhs, kSmiTagSize); 1285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(at, f12); 1286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_w(f12, f12); 1287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 1288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert lhs to a double format. t5 is scratch. 1290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t6, lhs); 1291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ConvertToDoubleStub stub2(a3, a2, t6, t5); 1292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ra); 12933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Call(stub2.GetCode()); 1294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ pop(ra); 1295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load rhs to a double in a1, a0. 1296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (rhs.is(a0)) { 1297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); 1298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 1299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 1301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); 1302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fall through to both_loaded_as_doubles. 130544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 130644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 130744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 130844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid EmitNanCheck(MacroAssembler* masm, Condition cc) { 1309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); 1310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 1311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 1312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Lhs and rhs are already loaded to f12 and f14 register pairs. 1313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(t0, t1, f14); 1314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(t2, t3, f12); 1315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Lhs and rhs are already loaded to GP registers. 1317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t0, a0); // a0 has LS 32 bits of rhs. 1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t1, a1); // a1 has MS 32 bits of rhs. 1319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t2, a2); // a2 has LS 32 bits of lhs. 1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t3, a3); // a3 has MS 32 bits of lhs. 1321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rhs_exponent = exp_first ? t0 : t1; 1323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register lhs_exponent = exp_first ? t2 : t3; 1324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rhs_mantissa = exp_first ? t1 : t0; 1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register lhs_mantissa = exp_first ? t3 : t2; 1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label one_is_nan, neither_is_nan; 1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label lhs_not_nan_exp_mask_is_loaded; 1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register exp_mask_reg = t4; 1330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(exp_mask_reg, HeapNumber::kExponentMask); 1331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ and_(t5, lhs_exponent, exp_mask_reg); 1332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&lhs_not_nan_exp_mask_is_loaded, ne, t5, Operand(exp_mask_reg)); 1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t5, lhs_exponent, HeapNumber::kNonMantissaBitsInTopWord); 1335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&one_is_nan, ne, t5, Operand(zero_reg)); 1336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&one_is_nan, ne, lhs_mantissa, Operand(zero_reg)); 1338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(exp_mask_reg, HeapNumber::kExponentMask); 1340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&lhs_not_nan_exp_mask_is_loaded); 1341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ and_(t5, rhs_exponent, exp_mask_reg); 1342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&neither_is_nan, ne, t5, Operand(exp_mask_reg)); 1344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t5, rhs_exponent, HeapNumber::kNonMantissaBitsInTopWord); 1346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&one_is_nan, ne, t5, Operand(zero_reg)); 1347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&neither_is_nan, eq, rhs_mantissa, Operand(zero_reg)); 1349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&one_is_nan); 1351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // NaN comparisons always fail. 1352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load whatever we need in v0 to make the comparison fail. 13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc == lt || cc == le) { 1355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(GREATER)); 1356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(LESS)); 1358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 1360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&neither_is_nan); 1362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc) { 1366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // f12 and f14 have the two doubles. Neither is a NaN. 1367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call a native function to do a comparison between two non-NaNs. 1368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call C routine that may not cause GC or other trouble. 1369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We use a call_was and return manually because we need arguments slots to 1370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // be freed. 1371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label return_result_not_equal, return_result_equal; 1373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc == eq) { 1374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Doubles are not equal unless they have the same bit pattern. 1375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Exception: 0 and -0. 1376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); 1377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 1378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 1379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Lhs and rhs are already loaded to f12 and f14 register pairs. 1380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(t0, t1, f14); 1381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(t2, t3, f12); 1382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Lhs and rhs are already loaded to GP registers. 1384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t0, a0); // a0 has LS 32 bits of rhs. 1385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t1, a1); // a1 has MS 32 bits of rhs. 1386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t2, a2); // a2 has LS 32 bits of lhs. 1387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t3, a3); // a3 has MS 32 bits of lhs. 1388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rhs_exponent = exp_first ? t0 : t1; 1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register lhs_exponent = exp_first ? t2 : t3; 1391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rhs_mantissa = exp_first ? t1 : t0; 1392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register lhs_mantissa = exp_first ? t3 : t2; 1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xor_(v0, rhs_mantissa, lhs_mantissa); 1395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_result_not_equal, ne, v0, Operand(zero_reg)); 1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(v0, rhs_exponent, lhs_exponent); 1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_result_equal, eq, v0, Operand(zero_reg)); 1399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 0, -0 case. 1400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(rhs_exponent, rhs_exponent, kSmiTagSize); 1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(lhs_exponent, lhs_exponent, kSmiTagSize); 1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(t4, rhs_exponent, lhs_exponent); 1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(t4, t4, rhs_mantissa); 1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_result_not_equal, ne, t4, Operand(zero_reg)); 1406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&return_result_equal); 14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(EQUAL)); 1410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&return_result_not_equal); 1414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!CpuFeatures::IsSupported(FPU)) { 1416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ra); 14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(0, 2, t4); 1418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!IsMipsSoftFloatABI) { 1419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We are not using MIPS FPU instructions, and parameters for the runtime 1420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // function call are prepaired in a0-a3 registers, but function we are 1421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // calling is compiled with hard-float flag and expecting hard float ABI 1422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // (parameters in f12/f14 registers). We need to copy parameters from 1423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0-a3 registers to f12/f14 register pairs. 1424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(f12, a0, a1); 1425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(f14, a2, a3); 1426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::compare_doubles(masm->isolate()), 14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 0, 2); 1431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ pop(ra); // Because this function returns int, result is in v0. 1432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 1435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label equal, less_than; 14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(&equal, NULL, eq, f12, f14); 14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(&less_than, NULL, lt, f12, f14); 14385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 143985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Not equal, not less, not NaN, must be greater. 14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(GREATER)); 1442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&equal); 1445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(EQUAL)); 1446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&less_than); 1449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(LESS)); 1450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, 1456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register lhs, 1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rhs) { 14583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If either operand is a JS object or an oddball value, then they are 1459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // not equal since their pointers are different. 1460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // There is no test for undetectability in strict equality. 14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); 1462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label first_non_object; 1463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the type of the first operand into a2 and compare it with 14643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // FIRST_SPEC_OBJECT_TYPE. 1465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(lhs, a2, a2); 14663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(&first_non_object, less, a2, Operand(FIRST_SPEC_OBJECT_TYPE)); 1467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return non-zero. 1469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label return_not_equal; 1470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&return_not_equal); 14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 1472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(1)); 1473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&first_non_object); 1475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for oddballs: true, false, null, undefined. 1476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_not_equal, eq, a2, Operand(ODDBALL_TYPE)); 1477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(rhs, a3, a3); 14793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(&return_not_equal, greater, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); 1480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for oddballs: true, false, null, undefined. 1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_not_equal, eq, a3, Operand(ODDBALL_TYPE)); 1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Now that we have the types we might as well check for symbol-symbol. 1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Ensure that no non-strings have the symbol bit set. 1486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask); 1487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSymbolTag != 0); 1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t2, a2, Operand(a3)); 1489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t0, t2, Operand(kIsSymbolMask)); 1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_not_equal, ne, t0, Operand(zero_reg)); 1491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, 1495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register lhs, 1496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rhs, 1497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* both_loaded_as_doubles, 1498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* not_heap_numbers, 1499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* slow) { 1500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(lhs, a3, a2); 1501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_heap_numbers, ne, a2, Operand(HEAP_NUMBER_TYPE)); 1502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(rhs, HeapObject::kMapOffset)); 1503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If first was a heap number & second wasn't, go to slow case. 1504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(slow, ne, a3, Operand(a2)); 1505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Both are heap numbers. Load them up then jump to the code we have 1507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // for that. 1508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 1512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 1514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(lhs, HeapNumber::kValueOffset + 4)); 1515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (rhs.is(a0)) { 1516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); 1517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 1518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 1520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); 1521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(both_loaded_as_doubles); 1524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Fast negative check for symbol-to-symbol equality. 1528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EmitCheckForSymbolsOrObjects(MacroAssembler* masm, 1529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register lhs, 1530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rhs, 1531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* possible_strings, 1532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* not_both_strings) { 1533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT((lhs.is(a0) && rhs.is(a1)) || 1534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (lhs.is(a1) && rhs.is(a0))); 1535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2 is object type of lhs. 1537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Ensure that no non-strings have the symbol bit set. 1538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label object_test; 1539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSymbolTag != 0); 1540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(at, a2, Operand(kIsNotStringMask)); 1541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&object_test, ne, at, Operand(zero_reg)); 1542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(at, a2, Operand(kIsSymbolMask)); 1543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(possible_strings, eq, at, Operand(zero_reg)); 1544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(rhs, a3, a3); 1545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_both_strings, ge, a3, Operand(FIRST_NONSTRING_TYPE)); 1546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(at, a3, Operand(kIsSymbolMask)); 1547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(possible_strings, eq, at, Operand(zero_reg)); 1548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Both are symbols. We already checked they weren't the same pointer 1550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // so they are not equal. 15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 1552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(1)); // Non-zero indicates not equal. 1553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&object_test); 15553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(not_both_strings, lt, a2, Operand(FIRST_SPEC_OBJECT_TYPE)); 1556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(rhs, a2, a3); 15573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(not_both_strings, lt, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); 1558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If both objects are undetectable, they are equal. Otherwise, they 1560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // are not equal, since they are different objects and an object is not 1561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // equal to undefined. 1562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(lhs, HeapObject::kMapOffset)); 1563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(a2, FieldMemOperand(a2, Map::kBitFieldOffset)); 1564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(a3, FieldMemOperand(a3, Map::kBitFieldOffset)); 1565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ and_(a0, a2, a3); 1566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a0, a0, Operand(1 << Map::kIsUndetectable)); 15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xori(v0, a0, 1 << Map::kIsUndetectable); 156944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 157044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 157144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 157244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, 157344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register object, 157444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result, 157544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 157644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 157744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch3, 157844f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool object_is_smi, 157944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* not_found) { 1580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use of registers. Register result is used as a temporary. 1581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register number_string_cache = result; 1582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register mask = scratch3; 1583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the number string cache. 1585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); 1586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make the hash mask from the length of the number string cache. It 1588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // contains two elements (number and string) for each cache entry. 1589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); 1590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Divide length by two (length is a smi). 1591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(mask, mask, kSmiTagSize + 1); 1592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(mask, mask, -1); // Make mask. 1593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate the entry in the number string cache. The hash value in the 1595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // number string cache for smis is just the smi value, and the hash for 1596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // doubles is the xor of the upper and lower words. See 1597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Heap::GetNumberStringCache. 1598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Isolate* isolate = masm->isolate(); 1599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label is_smi; 1600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label load_result_from_cache; 1601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!object_is_smi) { 1602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(object, &is_smi); 1603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 1604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 1605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(object, 1606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 1607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap::kHeapNumberMapRootIndex, 1608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch not_found, 1609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DONT_DO_SMI_CHECK); 1610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(8 == kDoubleSize); 1612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch1, 1613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch object, 1614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(HeapNumber::kValueOffset - kHeapObjectTag)); 1615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch2, MemOperand(scratch1, kPointerSize)); 1616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, MemOperand(scratch1, 0)); 1617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(scratch1, scratch1, Operand(scratch2)); 1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch1, scratch1, Operand(mask)); 1619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate address of entry in string cache: each entry consists 1621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // of two pointer sized fields. 1622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(scratch1, scratch1, kPointerSizeLog2 + 1); 1623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch1, number_string_cache, scratch1); 1624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register probe = mask; 1626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(probe, 1627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(scratch1, FixedArray::kHeaderSize)); 1628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(probe, not_found); 1629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f12, FieldMemOperand(object, HeapNumber::kValueOffset)); 1630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f14, FieldMemOperand(probe, HeapNumber::kValueOffset)); 16313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(&load_result_from_cache, NULL, eq, f12, f14); 1632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_found); 1633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Note that there is no cache check for non-FPU case, even though 1635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // it seems there could be. May be a tiny opimization for non-FPU 1636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // cores. 1637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_found); 1638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&is_smi); 1642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch = scratch1; 1643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(scratch, object, 1); // Shift away the tag. 1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch, mask, Operand(scratch)); 1645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate address of entry in string cache: each entry consists 1647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // of two pointer sized fields. 1648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(scratch, scratch, kPointerSizeLog2 + 1); 1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch, number_string_cache, scratch); 1650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the entry is the smi we are looking for. 1652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register probe = mask; 1653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); 1654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_found, ne, object, Operand(probe)); 1655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the result from the cache. 1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&load_result_from_cache); 1658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(result, 1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); 1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(isolate->counters()->number_to_string_native(), 1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1, 1663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 1664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2); 166544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 166644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 166744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 166844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid NumberToStringStub::Generate(MacroAssembler* masm) { 1669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label runtime; 1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, 0)); 1672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Generate code to lookup number in the number string cache. 1674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLookupNumberStringCache(masm, a1, v0, a2, a3, t0, false, &runtime); 16753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(1); 1676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&runtime); 1678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle number to string in the runtime system if not found in the cache. 1679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallRuntime(Runtime::kNumberToString, 1, 1); 168044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 168144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 168244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 168344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// On entry lhs_ (lhs) and rhs_ (rhs) are the things to be compared. 168444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// On exit, v0 is 0, positive, or negative (smi) to indicate the result 168544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// of the comparison. 168644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid CompareStub::Generate(MacroAssembler* masm) { 1687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow; // Call builtin. 1688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_smis, both_loaded_as_doubles; 1689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (include_smi_compare_) { 1692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_two_smis, smi_done; 1693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(a2, a1, a0); 1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(a2, ¬_two_smis); 1695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(a1, a1, 1); 1696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(a0, a0, 1); 16973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 16983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ subu(v0, a1, a0); 1699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_two_smis); 1700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (FLAG_debug_code) { 1701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(a2, a1, a0); 1702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a2, a2, kSmiTagMask); 1703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Assert(ne, "CompareStub: unexpected smi operands.", 1704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a2, Operand(zero_reg)); 1705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // NOTICE! This code is only reached after a smi-fast-case check, so 1709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // it is certain that at least one operand isn't a smi. 1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle the case where the objects are identical. Either returns the answer 1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // or goes to slow. Only falls through if the objects were not identical. 1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_); 1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If either is a Smi (we know that not both are), then they can only 1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // be strictly equal if the other is a HeapNumber. 1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(0, Smi::FromInt(0)); 1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t2, lhs_, Operand(rhs_)); 1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(t2, ¬_smis, t0); 1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // One operand is a smi. EmitSmiNonsmiComparison generates code that can: 1722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 1) Return the answer. 1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 2) Go to slow. 1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 3) Fall through to both_loaded_as_doubles. 1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 4) Jump to rhs_not_nan. 1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // In cases 3 and 4 we have found out we were dealing with a number-number 1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // comparison and the numbers have been loaded into f12 and f14 as doubles, 1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // or in GP registers (a0, a1, a2, a3) depending on the presence of the FPU. 1729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitSmiNonsmiComparison(masm, lhs_, rhs_, 1730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &both_loaded_as_doubles, &slow, strict_); 1731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&both_loaded_as_doubles); 1733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // f12, f14 are the double representations of the left hand side 1734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // and the right hand side if we have FPU. Otherwise a2, a3 represent 1735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // left hand side and a0, a1 represent right hand side. 1736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Isolate* isolate = masm->isolate(); 1738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 1739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 1740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label nan; 1741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t0, Operand(LESS)); 1742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t1, Operand(GREATER)); 1743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t2, Operand(EQUAL)); 1744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if either rhs or lhs is NaN. 17463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(NULL, &nan, eq, f12, f14); 1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if LESS condition is satisfied. If true, move conditionally 1749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // result to v0. 1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ c(OLT, D, f12, f14); 17513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movt(v0, t0); 1752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use previous check to store conditionally to v0 oposite condition 1753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // (GREATER). If rhs is equal to lhs, this will be corrected in next 1754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // check. 17553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movf(v0, t1); 1756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if EQUAL condition is satisfied. If true, move conditionally 1757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // result to v0. 1758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ c(EQ, D, f12, f14); 17593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movt(v0, t2); 1760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&nan); 1764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // NaN comparisons always fail. 1765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load whatever we need in v0 to make the comparison fail. 1766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc_ == lt || cc_ == le) { 1767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(GREATER)); 1768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(LESS)); 1770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Checks for NaN in the doubles we have loaded. Can return the answer or 1774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // fall through if neither is a NaN. Also binds rhs_not_nan. 1775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitNanCheck(masm, cc_); 1776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compares two doubles that are not NaNs. Returns the answer. 1778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Never falls through. 1779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitTwoNonNanDoubleComparison(masm, cc_); 1780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_smis); 1783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // At this point we know we are dealing with two different objects, 1784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // and neither of them is a Smi. The objects are in lhs_ and rhs_. 1785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (strict_) { 1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This returns non-equal for some object types, or falls through if it 1787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // was not lucky. 1788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitStrictTwoHeapObjectCompare(masm, lhs_, rhs_); 1789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label check_for_symbols; 1792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label flat_string_check; 1793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for heap-number-heap-number comparison. Can jump to slow case, 1794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // or load both doubles and jump to the code that handles 1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // that case. If the inputs are not doubles then jumps to check_for_symbols. 1796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // In this case a2 will contain the type of lhs_. 1797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitCheckForTwoHeapNumbers(masm, 1798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lhs_, 1799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rhs_, 1800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &both_loaded_as_doubles, 1801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &check_for_symbols, 1802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &flat_string_check); 1803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&check_for_symbols); 1805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc_ == eq && !strict_) { 1806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Returns an answer for two symbols or two detectable objects. 1807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Otherwise jumps to string case or not both strings case. 1808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Assumes that a2 is the type of lhs_ on entry. 1809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitCheckForSymbolsOrObjects(masm, lhs_, rhs_, &flat_string_check, &slow); 1810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for both being sequential ASCII strings, and inline if that is the 1813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // case. 1814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&flat_string_check); 1815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, a2, a3, &slow); 1817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(isolate->counters()->string_compare_native(), 1, a2, a3); 1819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc_ == eq) { 1820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringCompareStub::GenerateFlatAsciiStringEquals(masm, 1821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lhs_, 1822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rhs_, 1823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a2, 1824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a3, 1825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch t0); 1826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringCompareStub::GenerateCompareFlatAsciiStrings(masm, 1828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lhs_, 1829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rhs_, 1830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a2, 1831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a3, 1832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch t0, 1833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch t1); 1834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Never falls through to here. 1836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 1838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Prepare for call to builtin. Push object pointers, a0 (lhs) first, 1839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1 (rhs) second. 1840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(lhs_, rhs_); 1841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Figure out which native to call and setup the arguments. 1842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Builtins::JavaScript native; 1843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc_ == eq) { 1844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch native = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS; 1845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch native = Builtins::COMPARE; 1847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int ncr; // NaN compare result. 1848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cc_ == lt || cc_ == le) { 1849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ncr = GREATER; 1850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(cc_ == gt || cc_ == ge); // Remaining cases. 1852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ncr = LESS; 1853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a0, Operand(Smi::FromInt(ncr))); 1855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(a0); 1856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 1859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // tagged as a small integer. 1860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(native, JUMP_FUNCTION); 186144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 186244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 186344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 18643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// The stub expects its argument in the tos_ register and returns its result in 18653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// it, too: zero for false, and a non-zero value for true. 186644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid ToBooleanStub::Generate(MacroAssembler* masm) { 1867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub uses FPU instructions. 1868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 1869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label patch; 18713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Register map = t5.is(tos_) ? t3 : t5; 1872592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 18733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // undefined -> false. 18743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false); 18753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 18763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Boolean -> its value. 18773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false); 18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true); 18793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 18803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 'null' -> false. 18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false); 18823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 18833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (types_.Contains(SMI)) { 18843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Smis: 0 -> false, all other -> true 18853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(at, tos_, kSmiTagMask); 18863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // tos_ contains the correct return value already 18873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(eq, at, Operand(zero_reg)); 18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (types_.NeedsMap()) { 18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If we need a map later and have a Smi -> patch. 18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(tos_, &patch); 18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 18923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 18933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (types_.NeedsMap()) { 18943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(map, FieldMemOperand(tos_, HeapObject::kMapOffset)); 1895592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 18963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (types_.CanBeUndetectable()) { 18973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); 18983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(at, at, Operand(1 << Map::kIsUndetectable)); 18993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Undetectable -> false. 19003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movn(tos_, zero_reg, at); 19013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(ne, at, Operand(zero_reg)); 19023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 19033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 19043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (types_.Contains(SPEC_OBJECT)) { 19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Spec object -> true. 19073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); 19083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // tos_ contains the correct non-zero return value already. 19093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(ge, at, Operand(FIRST_SPEC_OBJECT_TYPE)); 19103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 19113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (types_.Contains(STRING)) { 19133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // String value -> false iff empty. 19143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); 19153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label skip; 19163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&skip, ge, at, Operand(FIRST_NONSTRING_TYPE)); 19173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); // the string length is OK as the return value 19183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(tos_, FieldMemOperand(tos_, String::kLengthOffset)); 19193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&skip); 19203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 19213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (types_.Contains(HEAP_NUMBER)) { 19233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Heap number -> false iff +0, -0, or NaN. 19243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label not_heap_number; 19253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); 19263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(¬_heap_number, ne, map, Operand(at)); 19273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label zero_or_nan, number; 19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldc1(f2, FieldMemOperand(tos_, HeapNumber::kValueOffset)); 19293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(&number, &zero_or_nan, ne, f2, kDoubleRegZero); 19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // "tos_" is a register, and contains a non zero value by default. 19313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Hence we only need to overwrite "tos_" with zero to return false for 19323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true. 19333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&zero_or_nan); 19343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(tos_, zero_reg); 19353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&number); 19363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 19373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_heap_number); 19383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 19393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&patch); 19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateTypeTransition(masm); 19423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 19433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ToBooleanStub::CheckOddball(MacroAssembler* masm, 19463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Type type, 19473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::RootListIndex value, 19483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool result) { 19493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (types_.Contains(type)) { 19503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If we see an expected oddball, return its ToBoolean value tos_. 19513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, value); 19523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Subu(at, at, tos_); // This is a check for equality for the movz below. 19533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The value of a root is never NULL, so we can avoid loading a non-null 19543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // value into tos_ when we want to return 'true'. 19553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!result) { 19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(tos_, zero_reg, at); 19573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 19583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(eq, at, Operand(zero_reg)); 19593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 19613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) { 19643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(a3, tos_); 19653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a2, Operand(Smi::FromInt(tos_.code()))); 19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a1, Operand(Smi::FromInt(types_.ToByte()))); 19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(a3, a2, a1); 19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Patch the caller to an appropriate specialized stub and return the 19693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // operation result to the caller of the stub. 19703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallExternalReference( 19713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()), 19723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3, 19733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1); 19743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 19753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 19783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We don't allow a GC during a store buffer overflow so there is no need to 19793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // store the registers in any particular way, but we do have to store and 19803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // restore them. 19813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ MultiPush(kJSCallerSaved | ra.bit()); 19823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (save_doubles_ == kSaveFPRegs) { 19833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CpuFeatures::Scope scope(FPU); 19843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ MultiPushFPU(kCallerSavedFPU); 19853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 19863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int argument_count = 1; 19873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int fp_argument_count = 0; 19883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Register scratch = a1; 19893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 19913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); 19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a0, Operand(ExternalReference::isolate_address())); 19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction( 19943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::store_buffer_overflow_function(masm->isolate()), 19953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch argument_count); 19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (save_doubles_ == kSaveFPRegs) { 19973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CpuFeatures::Scope scope(FPU); 19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ MultiPopFPU(kCallerSavedFPU); 19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 20013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ MultiPop(kJSCallerSaved | ra.bit()); 2002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 200344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 200444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 200544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid UnaryOpStub::PrintName(StringStream* stream) { 2007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const char* op_name = Token::Name(op_); 2008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const char* overwrite_name = NULL; // Make g++ happy. 2009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (mode_) { 2010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; 2011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; 2012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 20133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch stream->Add("UnaryOpStub_%s_%s_%s", 20143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch op_name, 20153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch overwrite_name, 20163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch UnaryOpIC::GetName(operand_type_)); 201744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 201844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 201944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// TODO(svenpanne): Use virtual functions instead of switch. 2021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::Generate(MacroAssembler* masm) { 2022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (operand_type_) { 2023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case UnaryOpIC::UNINITIALIZED: 2024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateTypeTransition(masm); 2025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case UnaryOpIC::SMI: 2027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiStub(masm); 2028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case UnaryOpIC::HEAP_NUMBER: 2030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapNumberStub(masm); 2031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case UnaryOpIC::GENERIC: 2033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateGenericStub(masm); 2034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 203644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 203744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 203844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 2040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument is in a0 and v0 at this point, so we can overwrite a0. 20413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ li(a2, Operand(Smi::FromInt(op_))); 20423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ li(a1, Operand(Smi::FromInt(mode_))); 2043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a0, Operand(Smi::FromInt(operand_type_))); 2044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(v0, a2, a1, a0); 2045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallExternalReference( 20473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1); 204844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 204944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 205044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// TODO(svenpanne): Use virtual functions instead of switch. 2052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 2053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 2054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 2055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiStubSub(masm); 2056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_NOT: 2058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiStubBitNot(masm); 2059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 2061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 2062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) { 2067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label non_smi, slow; 2068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiCodeSub(masm, &non_smi, &slow); 2069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&non_smi); 2070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 2071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateTypeTransition(masm); 2072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) { 2076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label non_smi; 2077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiCodeBitNot(masm, &non_smi); 2078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&non_smi); 2079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateTypeTransition(masm); 2080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, 2084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* non_smi, 2085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* slow) { 2086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(a0, non_smi); 2087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The result of negating zero or the smallest negative smi is not a smi. 2089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t0, a0, ~0x80000000); 2090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(slow, eq, t0, Operand(zero_reg)); 2091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return '0 - value'. 20933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 20943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ subu(v0, zero_reg, a0); 2095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm, 2099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* non_smi) { 2100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(a0, non_smi); 2101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Flip bits and revert inverted smi-tag. 2103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Neg(v0, a0); 2104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(v0, v0, ~kSmiTagMask); 2105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 210644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 210744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 210844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// TODO(svenpanne): Use virtual functions instead of switch. 2110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { 2111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 2112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 2113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapNumberStubSub(masm); 2114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_NOT: 2116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapNumberStubBitNot(masm); 2117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 2119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 2120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) { 2125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label non_smi, slow, call_builtin; 2126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiCodeSub(masm, &non_smi, &call_builtin); 2127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&non_smi); 2128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapNumberCodeSub(masm, &slow); 2129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 2130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateTypeTransition(masm); 2131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_builtin); 2132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateGenericCodeFallback(masm); 2133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateHeapNumberStubBitNot(MacroAssembler* masm) { 2137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label non_smi, slow; 2138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiCodeBitNot(masm, &non_smi); 2139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&non_smi); 2140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapNumberCodeBitNot(masm, &slow); 2141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 2142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateTypeTransition(masm); 2143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 21453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, 2147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* slow) { 2148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitCheckForHeapNumber(masm, a0, a1, t2, slow); 2149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0 is a heap number. Get a new heap number in a1. 2150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (mode_ == UNARY_OVERWRITE) { 2151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(a0, HeapNumber::kExponentOffset)); 2152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(a2, a2, Operand(HeapNumber::kSignMask)); // Flip sign. 2153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, FieldMemOperand(a0, HeapNumber::kExponentOffset)); 2154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow_allocate_heapnumber, heapnumber_allocated; 2156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(a1, a2, a3, t2, &slow_allocate_heapnumber); 2157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&heapnumber_allocated); 2158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow_allocate_heapnumber); 21603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 21623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(a0); 21633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kNumberAlloc, 0); 21643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(a1, v0); 21653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(a0); 21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&heapnumber_allocated); 2169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a0, HeapNumber::kMantissaOffset)); 2170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(a0, HeapNumber::kExponentOffset)); 2171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, FieldMemOperand(a1, HeapNumber::kMantissaOffset)); 2172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(a2, a2, Operand(HeapNumber::kSignMask)); // Flip sign. 2173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, FieldMemOperand(a1, HeapNumber::kExponentOffset)); 2174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, a1); 2175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateHeapNumberCodeBitNot( 2181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 2182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* slow) { 21833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label impossible; 21843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitCheckForHeapNumber(masm, a0, a1, t2, slow); 2186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert the heap number in a0 to an untagged integer in a1. 2187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ConvertToInt32(a0, a1, a2, a3, f0, slow); 2188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do the bitwise operation and check if the result fits in a smi. 2190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label try_float; 2191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Neg(a1, a1); 2192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a2, a1, Operand(0x40000000)); 2193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&try_float, lt, a2, Operand(zero_reg)); 2194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tag the result as a smi and we're done. 2196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiTag(v0, a1); 2197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Try to store the result in a heap number. 2200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&try_float); 2201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (mode_ == UNARY_NO_OVERWRITE) { 2202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow_allocate_heapnumber, heapnumber_allocated; 22033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Allocate a new heap number without zapping v0, which we need if it fails. 22043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AllocateHeapNumber(a2, a3, t0, t2, &slow_allocate_heapnumber); 2205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&heapnumber_allocated); 2206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow_allocate_heapnumber); 22083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 22093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(v0); // Push the heap number, not the untagged int32. 22113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kNumberAlloc, 0); 22123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(a2, v0); // Move the new heap number into a2. 22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the heap number into v0, now that the new heap number is in a2. 22143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(v0); 22153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 22173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Convert the heap number in v0 to an untagged integer in a1. 22183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This can't go slow-case because it's the same number we already 22193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // converted once again. 22203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ConvertToInt32(v0, a1, a3, t0, f0, &impossible); 22213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Negate the result. 22223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Xor(a1, a1, -1); 22233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&heapnumber_allocated); 22253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(v0, a2); // Move newly allocated heap number to v0. 2226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 2229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert the int32 in a1 to the heap number in v0. a2 is corrupted. 2230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 2231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(a1, f0); 2232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_w(f0, f0); 2233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); 2234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // WriteInt32ToHeapNumberStub does not trigger GC, so we do not 2237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have to set up a frame. 2238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch WriteInt32ToHeapNumberStub stub(a1, v0, a2, a3); 2239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 2240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 22413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 22423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&impossible); 22433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (FLAG_debug_code) { 22443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ stop("Incorrect assumption in bit-not stub"); 22453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 2246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// TODO(svenpanne): Use virtual functions instead of switch. 2250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) { 2251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 2252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 2253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateGenericStubSub(masm); 2254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_NOT: 2256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateGenericStubBitNot(masm); 2257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 2259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 2260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) { 2265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label non_smi, slow; 2266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiCodeSub(masm, &non_smi, &slow); 2267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&non_smi); 2268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapNumberCodeSub(masm, &slow); 2269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 2270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateGenericCodeFallback(masm); 2271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) { 2275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label non_smi, slow; 2276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiCodeBitNot(masm, &non_smi); 2277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&non_smi); 2278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapNumberCodeBitNot(masm, &slow); 2279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 2280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateGenericCodeFallback(masm); 2281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid UnaryOpStub::GenerateGenericCodeFallback( 2285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm) { 2286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle the slow case by jumping to the JavaScript builtin. 2287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(a0); 2288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 2289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 2290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); 2291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_NOT: 2293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); 2294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 2296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 2297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 2302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label get_result; 2303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(a1, a0); 2305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a2, Operand(Smi::FromInt(MinorKey()))); 2307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a1, Operand(Smi::FromInt(op_))); 2308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a0, Operand(Smi::FromInt(operands_type_))); 2309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(a2, a1, a0); 2310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallExternalReference( 2312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference(IC_Utility(IC::kBinaryOp_Patch), 2313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()), 2314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5, 2315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1); 231644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 231744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 231844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateTypeTransitionWithSavedArgs( 232044f0eee88ff00398ff7f715fab053374d808c90dSteve Block MacroAssembler* masm) { 232144f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNIMPLEMENTED(); 232244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 232344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 232444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::Generate(MacroAssembler* masm) { 23263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Explicitly allow generation of nested stubs. It is safe here because 23273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // generation code does not use any raw pointers. 23283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowStubCallsScope allow_stub_calls(masm, true); 2329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (operands_type_) { 2330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case BinaryOpIC::UNINITIALIZED: 2331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateTypeTransition(masm); 2332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case BinaryOpIC::SMI: 2334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiStub(masm); 2335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case BinaryOpIC::INT32: 2337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateInt32Stub(masm); 2338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case BinaryOpIC::HEAP_NUMBER: 2340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapNumberStub(masm); 2341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case BinaryOpIC::ODDBALL: 2343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateOddballStub(masm); 2344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case BinaryOpIC::BOTH_STRING: 2346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateBothStringStub(masm); 2347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case BinaryOpIC::STRING: 2349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateStringStub(masm); 2350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case BinaryOpIC::GENERIC: 2352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateGeneric(masm); 2353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 2355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 2356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 235744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 235844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 235944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 23603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid BinaryOpStub::PrintName(StringStream* stream) { 2361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const char* op_name = Token::Name(op_); 2362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const char* overwrite_name; 2363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (mode_) { 2364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case NO_OVERWRITE: overwrite_name = "Alloc"; break; 2365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 2366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; 2367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: overwrite_name = "UnknownOverwrite"; break; 2368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 23693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch stream->Add("BinaryOpStub_%s_%s_%s", 23703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch op_name, 23713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch overwrite_name, 23723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch BinaryOpIC::GetName(operands_type_)); 237344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 237444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 237544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 237644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateSmiSmiOperation(MacroAssembler* masm) { 2378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = a1; 2379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right = a0; 2380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1 = t0; 2382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2 = t1; 2383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(right.is(a0)); 2385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 2386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_smi_result; 2388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 2389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::ADD: 2390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AdduAndCheckForOverflow(v0, left, right, scratch1); 2391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ RetOnNoOverflow(scratch1); 2392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // No need to revert anything - right and left are intact. 2393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 2395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SubuAndCheckForOverflow(v0, left, right, scratch1); 2396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ RetOnNoOverflow(scratch1); 2397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // No need to revert anything - right and left are intact. 2398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::MUL: { 2400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Remove tag from one of the operands. This way the multiplication result 2401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // will be a smi if it fits the smi range. 2402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(scratch1, right); 2403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do multiplication. 2404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // lo = lower 32 bits of scratch1 * left. 2405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // hi = higher 32 bits of scratch1 * left. 2406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Mult(left, scratch1); 2407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for overflowing the smi range - no overflow if higher 33 bits of 2408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the result are identical. 2409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mflo(scratch1); 2410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mfhi(scratch2); 2411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(scratch1, scratch1, 31); 2412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_smi_result, ne, scratch1, Operand(scratch2)); 2413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Go slow on zero result to handle -0. 2414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mflo(v0); 2415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(ne, v0, Operand(zero_reg)); 2416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We need -0 if we were multiplying a negative number with 0 to get 0. 2417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We know one of them was zero. 2418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch2, right, left); 2419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip; 2420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ARM uses the 'pl' condition, which is 'ge'. 2421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Negating it results in 'lt'. 2422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&skip, lt, scratch2, Operand(zero_reg)); 2423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(Smi::FromInt(0) == 0); 24243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 24253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(v0, zero_reg); // Return smi 0 if the non-zero one was positive. 2426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&skip); 2427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We fall through here if we multiplied a negative number with 0, because 2428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // that would mean we should produce -0. 2429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::DIV: { 2432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 2433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(scratch2, right); 2434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(scratch1, left); 2435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Div(scratch1, scratch2); 2436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // A minor optimization: div may be calculated asynchronously, so we check 2437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // for division by zero before getting the result. 2438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_smi_result, eq, scratch2, Operand(zero_reg)); 2439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the result is 0, we need to make sure the dividsor (right) is 2440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // positive, otherwise it is a -0 case. 2441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Quotient is in 'lo', remainder is in 'hi'. 2442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for no remainder first. 2443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mfhi(scratch1); 2444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_smi_result, ne, scratch1, Operand(zero_reg)); 2445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mflo(scratch1); 2446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, ne, scratch1, Operand(zero_reg)); 2447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_smi_result, lt, scratch2, Operand(zero_reg)); 2448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 2449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the signed result fits in a Smi. 2450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch2, scratch1, Operand(0x40000000)); 2451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_smi_result, lt, scratch2, Operand(zero_reg)); 2452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiTag(v0, scratch1); 2453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::MOD: { 2457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 2458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(scratch2, right); 2459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(scratch1, left); 2460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Div(scratch1, scratch2); 2461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // A minor optimization: div may be calculated asynchronously, so we check 2462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // for division by 0 before calling mfhi. 2463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for zero on the right hand side. 2464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_smi_result, eq, scratch2, Operand(zero_reg)); 2465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the result is 0, we need to make sure the dividend (left) is 2466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // positive (or 0), otherwise it is a -0 case. 2467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Remainder is in 'hi'. 2468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mfhi(scratch2); 2469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, ne, scratch2, Operand(zero_reg)); 2470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_smi_result, lt, scratch1, Operand(zero_reg)); 2471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 2472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the signed result fits in a Smi. 2473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch1, scratch2, Operand(0x40000000)); 2474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_smi_result, lt, scratch1, Operand(zero_reg)); 2475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiTag(v0, scratch2); 2476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_OR: 24803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 24813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(v0, left, right); 2482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_AND: 24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 24853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ and_(v0, left, right); 2486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_XOR: 24883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 24893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xor_(v0, left, right); 2490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SAR: 2492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Remove tags from right operand. 2493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetLeastBitsFromSmi(scratch1, right, 5); 2494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srav(scratch1, left, scratch1); 2495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Smi tag result. 24963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(v0, scratch1, ~kSmiTagMask); 2497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHR: 2500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Remove tags from operands. We can't do this on a 31 bit number 2501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // because then the 0s get shifted into bit 30 instead of bit 31. 2502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(scratch1, left); 2503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetLeastBitsFromSmi(scratch2, right, 5); 2504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srlv(v0, scratch1, scratch2); 2505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Unsigned shift is not allowed to produce a negative number, so 2506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // check the sign bit and the sign bit after Smi tagging. 2507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch1, v0, Operand(0xc0000000)); 2508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_smi_result, ne, scratch1, Operand(zero_reg)); 2509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Smi tag result. 2510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiTag(v0); 2511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHL: 2514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Remove tags from operands. 2515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(scratch1, left); 2516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetLeastBitsFromSmi(scratch2, right, 5); 2517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(scratch1, scratch1, scratch2); 2518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the signed result fits in a Smi. 2519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch2, scratch1, Operand(0x40000000)); 2520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_smi_result, lt, scratch2, Operand(zero_reg)); 2521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiTag(v0, scratch1); 2522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 2525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 2526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_smi_result); 252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 252944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 253044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateFPOperation(MacroAssembler* masm, 2532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool smi_operands, 2533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* not_numbers, 2534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* gc_required) { 2535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = a1; 2536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right = a0; 2537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1 = t3; 2538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2 = t5; 2539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch3 = t0; 2540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(smi_operands || (not_numbers != NULL)); 2542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_operands && FLAG_debug_code) { 2543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AbortIfNotSmi(left); 2544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AbortIfNotSmi(right); 2545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register heap_number_map = t2; 2548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 2549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 2551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::ADD: 2552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 2553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::MUL: 2554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::DIV: 2555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::MOD: { 2556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load left and right operands into f12 and f14 or a0/a1 and a2/a3 2557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // depending on whether FPU is available or not. 2558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::Destination destination = 2559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::IsSupported(FPU) && 2560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch op_ != Token::MOD ? 2561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::kFPURegisters : 2562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::kCoreRegisters; 2563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate new heap number for result. 2565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result = s0; 2566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapResultAllocation( 2567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm, result, heap_number_map, scratch1, scratch2, gc_required); 2568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the operands. 2570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_operands) { 2571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); 2572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::LoadOperands(masm, 2574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch destination, 2575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_map, 2576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 2577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 2578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch not_numbers); 2579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate the result. 2582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (destination == FloatingPointHelper::kFPURegisters) { 2583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Using FPU registers: 2584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // f12: Left value. 2585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // f14: Right value. 2586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 2587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 2588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::ADD: 2589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ add_d(f10, f12, f14); 2590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 2592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sub_d(f10, f12, f14); 2593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::MUL: 2595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mul_d(f10, f12, f14); 2596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::DIV: 2598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ div_d(f10, f12, f14); 2599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 2601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 2602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ARM uses a workaround here because of the unaligned HeapNumber 2605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // kValueOffset. On MIPS this workaround is built into sdc1 so 2606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // there's no point in generating even more instructions. 2607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f10, FieldMemOperand(result, HeapNumber::kValueOffset)); 26083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 2609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, result); 2610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call the C function to handle the double operation. 2612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::CallCCodeForDoubleOperation(masm, 2613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch op_, 2614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch result, 2615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1); 2616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (FLAG_debug_code) { 2617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ stop("Unreachable code."); 2618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_OR: 2623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_XOR: 2624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_AND: 2625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SAR: 2626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHR: 2627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHL: { 2628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_operands) { 2629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(a3, left); 2630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(a2, right); 2631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert operands to 32-bit integers. Right in a2 and left in a3. 2633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::ConvertNumberToInt32(masm, 2634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch left, 2635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a3, 2636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_map, 2637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 2638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 2639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch3, 2640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch f0, 2641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch not_numbers); 2642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::ConvertNumberToInt32(masm, 2643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch right, 2644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a2, 2645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_map, 2646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 2647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 2648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch3, 2649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch f0, 2650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch not_numbers); 2651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label result_not_a_smi; 2653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 2654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_OR: 2655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(a2, a3, Operand(a2)); 2656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_XOR: 2658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(a2, a3, Operand(a2)); 2659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_AND: 2661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a2, a3, Operand(a2)); 2662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SAR: 2664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use only the 5 least significant bits of the shift count. 2665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetLeastBitsFromInt32(a2, a2, 5); 2666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srav(a2, a3, a2); 2667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHR: 2669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use only the 5 least significant bits of the shift count. 2670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetLeastBitsFromInt32(a2, a2, 5); 2671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srlv(a2, a3, a2); 2672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // SHR is special because it is required to produce a positive answer. 2673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The code below for writing into heap numbers isn't capable of 2674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // writing the register as an unsigned int so we go to slow case if we 2675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // hit this case. 2676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 2677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&result_not_a_smi, lt, a2, Operand(zero_reg)); 2678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_numbers, lt, a2, Operand(zero_reg)); 2680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHL: 2683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use only the 5 least significant bits of the shift count. 2684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetLeastBitsFromInt32(a2, a2, 5); 2685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(a2, a3, a2); 2686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 2688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 2689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the *signed* result fits in a smi. 2691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a3, a2, Operand(0x40000000)); 2692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&result_not_a_smi, lt, a3, Operand(zero_reg)); 2693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiTag(v0, a2); 2694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate new heap number for result. 2697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&result_not_a_smi); 2698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result = t1; 2699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_operands) { 2700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber( 2701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch result, scratch1, scratch2, heap_number_map, gc_required); 2702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapResultAllocation( 2704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm, result, heap_number_map, scratch1, scratch2, gc_required); 2705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: Answer as signed int32. 2708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t1: Heap number to write answer into. 2709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Nothing can go wrong now, so move the heap number to v0, which is the 2711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // result. 2712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, t1); 2713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 2715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert the int32 in a2 to the heap number in a0. As 2716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // mentioned above SHR needs to always produce a positive result. 2717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 2718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(a2, f0); 2719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (op_ == Token::SHR) { 272069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Cvt_d_uw(f0, f0, f22); 2721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_w(f0, f0); 2723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ARM uses a workaround here because of the unaligned HeapNumber 2725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // kValueOffset. On MIPS this workaround is built into sdc1 so 2726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // there's no point in generating even more instructions. 2727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); 2728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tail call that writes the int32 in a2 to the heap number in v0, using 2731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3 and a0 as scratch. v0 is preserved and returned. 2732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch WriteInt32ToHeapNumberStub stub(a2, v0, a3, a0); 2733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallStub(&stub); 2734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 2738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 2739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 274044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 274144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 274244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 274344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Generate the smi code. If the operation on smis are successful this return is 274444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// generated. If the result is not a smi and heap number allocation is not 274544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// requested the code falls through. If number allocation is requested but a 274644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// heap number cannot be allocated the code jumps to the lable gc_required. 2747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateSmiCode( 2748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 2749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* use_runtime, 275044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* gc_required, 275144f0eee88ff00398ff7f715fab053374d808c90dSteve Block SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { 2752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_smis; 2753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = a1; 2755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right = a0; 2756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1 = t3; 2757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Perform combined smi check on both operands. 2759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(scratch1, left, Operand(right)); 2760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 2761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(scratch1, ¬_smis); 2762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the smi-smi operation results in a smi return is generated. 2764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiSmiOperation(masm); 2765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If heap number results are possible generate the result in an allocated 2767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // heap number. 2768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { 2769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateFPOperation(masm, true, use_runtime, gc_required); 2770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_smis); 277244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 277344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 277444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 2776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_smis, call_runtime; 2777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (result_type_ == BinaryOpIC::UNINITIALIZED || 2779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch result_type_ == BinaryOpIC::SMI) { 2780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Only allow smi results. 2781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiCode(masm, &call_runtime, NULL, NO_HEAPNUMBER_RESULTS); 2782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allow heap number result and don't make a transition if a heap number 2784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // cannot be allocated. 2785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiCode(masm, 2786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &call_runtime, 2787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &call_runtime, 2788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ALLOW_HEAPNUMBER_RESULTS); 2789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Code falls through if the result is not returned as either a smi or heap 2792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // number. 2793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateTypeTransition(masm); 2794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_runtime); 2796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateCallRuntime(masm); 279744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 279844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 279944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateStringStub(MacroAssembler* masm) { 2801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(operands_type_ == BinaryOpIC::STRING); 2802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Try to add arguments as strings, otherwise, transition to the generic 2803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // BinaryOpIC type. 2804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateAddStrings(masm); 2805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateTypeTransition(masm); 280644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 280744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 280844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) { 2810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label call_runtime; 2811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING); 2812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(op_ == Token::ADD); 2813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If both arguments are strings, call the string add stub. 2814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Otherwise, do a transition. 2815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers containing left and right operands respectively. 2817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = a1; 2818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right = a0; 2819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Test if left operand is a string. 2821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(left, &call_runtime); 2822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(left, a2, a2); 2823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&call_runtime, ge, a2, Operand(FIRST_NONSTRING_TYPE)); 2824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Test if right operand is a string. 2826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(right, &call_runtime); 2827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(right, a2, a2); 2828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&call_runtime, ge, a2, Operand(FIRST_NONSTRING_TYPE)); 2829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); 2831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateRegisterArgsPush(masm); 2832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallStub(&string_add_stub); 2833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_runtime); 2835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateTypeTransition(masm); 283644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 283744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 283844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { 2840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(operands_type_ == BinaryOpIC::INT32); 2841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = a1; 2843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right = a0; 2844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1 = t3; 2845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2 = t5; 2846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FPURegister double_scratch = f0; 2847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FPURegister single_scratch = f6; 2848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register heap_number_result = no_reg; 2850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register heap_number_map = t2; 2851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 2852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label call_runtime; 2854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Labels for type transition, used for wrong input or output types. 2855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Both label are currently actually bound to the same position. We use two 2856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // different label to differentiate the cause leading to type transition. 2857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label transition; 2858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Smi-smi fast case. 2860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip; 2861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(scratch1, left, right); 2862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(scratch1, &skip); 2863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiSmiOperation(masm); 2864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fall through if the result is not a smi. 2865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&skip); 2866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 2868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::ADD: 2869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 2870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::MUL: 2871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::DIV: 2872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::MOD: { 28733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Load both operands and check that they are 32-bit integer. 28743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Jump to type transition if they are not. The registers a0 and a1 (right 28753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // and left) are preserved for the runtime call. 28763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FloatingPointHelper::Destination destination = 28773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch (CpuFeatures::IsSupported(FPU) && op_ != Token::MOD) 28783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ? FloatingPointHelper::kFPURegisters 28793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : FloatingPointHelper::kCoreRegisters; 28803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 28813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FloatingPointHelper::LoadNumberAsInt32Double(masm, 28823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch right, 28833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch destination, 28843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch f14, 28853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch a2, 28863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch a3, 28873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch heap_number_map, 28883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch scratch1, 28893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch scratch2, 28903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch f2, 28913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch &transition); 28923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FloatingPointHelper::LoadNumberAsInt32Double(masm, 28933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch left, 28943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch destination, 28953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch f12, 28963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch t0, 28973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch t1, 28983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch heap_number_map, 28993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch scratch1, 29003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch scratch2, 29013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch f2, 29023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch &transition); 2903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (destination == FloatingPointHelper::kFPURegisters) { 2905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 2906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label return_heap_number; 2907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 2908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::ADD: 2909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ add_d(f10, f12, f14); 2910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 2912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sub_d(f10, f12, f14); 2913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::MUL: 2915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mul_d(f10, f12, f14); 2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::DIV: 2918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ div_d(f10, f12, f14); 2919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 2921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 2922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (op_ != Token::DIV) { 2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // These operations produce an integer result. 2926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Try to return a smi if we can. 2927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Otherwise return a heap number if allowed, or jump to type 2928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // transition. 2929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 29303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register except_flag = scratch2; 29313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ EmitFPUTruncate(kRoundToZero, 29323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch single_scratch, 29333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch f10, 29343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, 29353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch except_flag); 2936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (result_type_ <= BinaryOpIC::INT32) { 29383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If except_flag != 0, result does not fit in a 32-bit integer. 29393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&transition, ne, except_flag, Operand(zero_reg)); 2940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the result fits in a smi. 2943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mfc1(scratch1, single_scratch); 2944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch2, scratch1, Operand(0x40000000)); 2945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If not try to return a heap number. 2946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_heap_number, lt, scratch2, Operand(zero_reg)); 2947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for minus zero. Return heap number for minus zero. 2948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_zero; 2949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_zero, ne, scratch1, Operand(zero_reg)); 2950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mfc1(scratch2, f11); 2951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch2, scratch2, HeapNumber::kSignMask); 2952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_heap_number, ne, scratch2, Operand(zero_reg)); 2953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_zero); 2954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tag the result and return. 2956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiTag(v0, scratch1); 2957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // DIV just falls through to allocating a heap number. 2960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 29623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&return_heap_number); 29633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Return a heap number, or fall through to type transition or runtime 29643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // call if we can't. 29653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (result_type_ >= ((op_ == Token::DIV) ? BinaryOpIC::HEAP_NUMBER 29663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : BinaryOpIC::INT32)) { 2967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We are using FPU registers so s0 is available. 2968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_result = s0; 2969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapResultAllocation(masm, 2970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_result, 2971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_map, 2972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 2973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 2974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &call_runtime); 2975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, heap_number_result); 2976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f10, FieldMemOperand(v0, HeapNumber::kValueOffset)); 2977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // A DIV operation expecting an integer result falls through 2981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // to type transition. 2982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We preserved a0 and a1 to be able to call runtime. 2985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Save the left value on the stack. 2986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(t1, t0); 2987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label pop_and_call_runtime; 2989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a heap number to store the result. 2991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_result = s0; 2992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapResultAllocation(masm, 2993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_result, 2994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_map, 2995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 2996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 2997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &pop_and_call_runtime); 2998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the left value from the value saved on the stack. 3000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Pop(a1, a0); 3001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call the C function to handle the double operation. 3003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::CallCCodeForDoubleOperation( 3004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm, op_, heap_number_result, scratch1); 3005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (FLAG_debug_code) { 3006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ stop("Unreachable code."); 3007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&pop_and_call_runtime); 3010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(2); 3011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&call_runtime); 3012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_OR: 3018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_XOR: 3019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_AND: 3020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SAR: 3021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHR: 3022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHL: { 3023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label return_heap_number; 3024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch3 = t1; 3025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert operands to 32-bit integers. Right in a2 and left in a3. The 3026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // registers a0 and a1 (right and left) are preserved for the runtime 3027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // call. 3028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::LoadNumberAsInt32(masm, 3029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch left, 3030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a3, 3031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_map, 3032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 3033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 3034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch3, 3035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch f0, 3036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &transition); 3037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::LoadNumberAsInt32(masm, 3038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch right, 3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a2, 3040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_map, 3041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 3042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 3043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch3, 3044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch f0, 3045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &transition); 3046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The ECMA-262 standard specifies that, for shift operations, only the 3048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 5 least significant bits of the shift value should be used. 3049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 3050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_OR: 3051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(a2, a3, Operand(a2)); 3052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_XOR: 3054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(a2, a3, Operand(a2)); 3055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_AND: 3057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a2, a3, Operand(a2)); 3058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SAR: 3060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a2, a2, Operand(0x1f)); 3061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srav(a2, a3, a2); 3062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHR: 3064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a2, a2, Operand(0x1f)); 3065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srlv(a2, a3, a2); 3066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // SHR is special because it is required to produce a positive answer. 3067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We only get a negative result if the shift value (a2) is 0. 3068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This result cannot be respresented as a signed 32-bit integer, try 3069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // to return a heap number if we can. 3070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The non FPU code does not support this special case, so jump to 3071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // runtime if we don't support it. 3072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 3073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch((result_type_ <= BinaryOpIC::INT32) 3074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? &transition 3075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : &return_heap_number, 3076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lt, 3077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a2, 3078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(zero_reg)); 3079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch((result_type_ <= BinaryOpIC::INT32) 3081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? &transition 3082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : &call_runtime, 3083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lt, 3084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a2, 3085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(zero_reg)); 3086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHL: 3089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a2, a2, Operand(0x1f)); 3090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(a2, a3, a2); 3091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 3093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 3094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the result fits in a smi. 3097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch1, a2, Operand(0x40000000)); 3098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If not try to return a heap number. (We know the result is an int32.) 3099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_heap_number, lt, scratch1, Operand(zero_reg)); 3100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tag the result and return. 3101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiTag(v0, a2); 3102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&return_heap_number); 3105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_result = t1; 3106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapResultAllocation(masm, 3107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_result, 3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch heap_number_map, 3109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 3111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &call_runtime); 3112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 3114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 3115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (op_ != Token::SHR) { 3117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert the result to a floating point value. 3118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(a2, double_scratch); 3119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_w(double_scratch, double_scratch); 3120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The result must be interpreted as an unsigned 32-bit integer. 3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(a2, double_scratch); 312369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Cvt_d_uw(double_scratch, double_scratch, single_scratch); 3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Store the result. 3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, heap_number_result); 3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(double_scratch, FieldMemOperand(v0, HeapNumber::kValueOffset)); 3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tail call that writes the int32 in a2 to the heap number in v0, using 31323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a3 and a0 as scratch. v0 is preserved and returned. 3133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(a0, t1); 31343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch WriteInt32ToHeapNumberStub stub(a2, v0, a3, a0); 3135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallStub(&stub); 3136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 3142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 3143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 31453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We never expect DIV to yield an integer result, so we always generate 31463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // type transition code for DIV operations expecting an integer result: the 31473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // code will fall through to this type transition. 31483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (transition.is_linked() || 31493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ((op_ == Token::DIV) && (result_type_ <= BinaryOpIC::INT32))) { 3150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&transition); 3151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateTypeTransition(masm); 3152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_runtime); 3155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateCallRuntime(masm); 315644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 315744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 315844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { 3160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label call_runtime; 3161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (op_ == Token::ADD) { 3163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle string addition here, because it is the only operation 3164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // that does not do a ToNumber conversion on the operands. 3165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateAddStrings(masm); 3166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert oddball arguments to numbers. 3169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label check, done; 3170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); 3171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&check, ne, a1, Operand(t0)); 3172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (Token::IsBitOp(op_)) { 3173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a1, Operand(Smi::FromInt(0))); 3174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(a1, Heap::kNanValueRootIndex); 3176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done); 3178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&check); 3179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); 3180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, ne, a0, Operand(t0)); 3181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (Token::IsBitOp(op_)) { 3182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a0, Operand(Smi::FromInt(0))); 3183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(a0, Heap::kNanValueRootIndex); 3185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 3187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateHeapNumberStub(masm); 318944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 319044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 319144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { 3193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label call_runtime; 3194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateFPOperation(masm, false, &call_runtime, &call_runtime); 3195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_runtime); 3197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateCallRuntime(masm); 319844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 319944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 320044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateGeneric(MacroAssembler* masm) { 3202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label call_runtime, call_string_add_or_runtime; 3203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateSmiCode(masm, &call_runtime, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); 3205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateFPOperation(masm, false, &call_string_add_or_runtime, &call_runtime); 3207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_string_add_or_runtime); 3209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (op_ == Token::ADD) { 3210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateAddStrings(masm); 3211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_runtime); 3214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateCallRuntime(masm); 3215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { 3219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(op_ == Token::ADD); 3220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label left_not_string, call_runtime; 3221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = a1; 3223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right = a0; 3224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if left argument is a string. 3226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(left, &left_not_string); 3227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(left, a2, a2); 3228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&left_not_string, ge, a2, Operand(FIRST_NONSTRING_TYPE)); 3229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); 3231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateRegisterArgsPush(masm); 3232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallStub(&string_add_left_stub); 3233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Left operand is not a string, test right. 3235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&left_not_string); 3236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(right, &call_runtime); 3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(right, a2, a2); 3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&call_runtime, ge, a2, Operand(FIRST_NONSTRING_TYPE)); 3239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); 3241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateRegisterArgsPush(masm); 3242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallStub(&string_add_right_stub); 3243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // At least one argument is not a string. 3245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_runtime); 3246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) { 3250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateRegisterArgsPush(masm); 3251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (op_) { 3252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::ADD: 3253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); 3254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 3256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); 3257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::MUL: 3259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION); 3260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::DIV: 3262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION); 3263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::MOD: 3265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); 3266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_OR: 3268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION); 3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_AND: 3271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::BIT_AND, JUMP_FUNCTION); 3272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_XOR: 3274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_FUNCTION); 3275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SAR: 3277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::SAR, JUMP_FUNCTION); 3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHR: 3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); 3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SHL: 3283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION); 3284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 3286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 3287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 328844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 328944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 329044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateHeapResultAllocation( 329244f0eee88ff00398ff7f715fab053374d808c90dSteve Block MacroAssembler* masm, 329344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result, 329444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register heap_number_map, 329544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 329644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 329744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* gc_required) { 3298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Code below will scratch result if allocation fails. To keep both arguments 3300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // intact for the runtime call result cannot be one of these. 3301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!result.is(a0) && !result.is(a1)); 3302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (mode_ == OVERWRITE_LEFT || mode_ == OVERWRITE_RIGHT) { 3304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip_allocation, allocated; 3305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register overwritable_operand = mode_ == OVERWRITE_LEFT ? a1 : a0; 3306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the overwritable operand is already an object, we skip the 3307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // allocation of a heap number. 3308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(overwritable_operand, &skip_allocation); 3309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a heap number for the result. 3310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber( 3311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch result, scratch1, scratch2, heap_number_map, gc_required); 3312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&allocated); 3313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&skip_allocation); 3314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use object holding the overwritable operand for result. 3315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(result, overwritable_operand); 3316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&allocated); 3317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(mode_ == NO_OVERWRITE); 3319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber( 3320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch result, scratch1, scratch2, heap_number_map, gc_required); 3321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 332244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 332344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 332444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { 3326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(a1, a0); 332744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 332844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 332944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 333044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 333144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid TranscendentalCacheStub::Generate(MacroAssembler* masm) { 3332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Untagged case: double input in f4, double result goes 3333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // into f4. 3334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tagged case: tagged input on top of stack and in a0, 3335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // tagged result (heap number) goes into v0. 3336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label input_not_smi; 3338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label loaded; 3339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label calculate; 3340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label invalid_cache; 3341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Register scratch0 = t5; 3342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Register scratch1 = t3; 3343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Register cache_entry = a0; 3344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const bool tagged = (argument_type_ == TAGGED); 3345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 3347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 3348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (tagged) { 3350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument is a number and is on stack and in a0. 3351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load argument and check if it is a smi. 3352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(a0, &input_not_smi); 3353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Input is a smi. Convert to double and load the low and high words 3355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // of the double into a2, a3. 3356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(t0, a0, kSmiTagSize); 3357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(t0, f4); 3358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_w(f4, f4); 3359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(a2, a3, f4); 3360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&loaded); 3361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&input_not_smi); 3363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if input is a HeapNumber. 3364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(a0, 3365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a1, 3366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap::kHeapNumberMapRootIndex, 3367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &calculate, 3368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DONT_DO_SMI_CHECK); 3369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Input is a HeapNumber. Store the 3370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // low and high words into a2, a3. 3371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(a0, HeapNumber::kValueOffset)); 3372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a0, HeapNumber::kValueOffset + 4)); 3373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Input is untagged double in f4. Output goes to f4. 3375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(a2, a3, f4); 3376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&loaded); 3378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2 = low 32 bits of double value. 3379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3 = high 32 bits of double value. 3380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute hash (the shifts are arithmetic): 3381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1); 3382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(a1, a2, a3); 3383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(t0, a1, 16); 3384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(a1, a1, t0); 3385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(t0, a1, 8); 3386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(a1, a1, t0); 3387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize)); 3388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a1, a1, Operand(TranscendentalCache::SubCache::kCacheSize - 1)); 3389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2 = low 32 bits of double value. 3391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3 = high 32 bits of double value. 3392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1 = TranscendentalCache::hash(double value). 3393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(cache_entry, Operand( 3394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference::transcendental_cache_array_address( 3395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()))); 3396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0 points to cache array. 3397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(cache_entry, MemOperand(cache_entry, type_ * sizeof( 3398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Isolate::Current()->transcendental_cache()->caches_[0]))); 3399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0 points to the cache for the type type_. 3400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If NULL, the cache hasn't been initialized yet, so go through runtime. 3401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&invalid_cache, eq, cache_entry, Operand(zero_reg)); 3402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG 3404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the layout of cache elements match expectations. 3405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch { TranscendentalCache::SubCache::Element test_elem[2]; 3406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char* elem_start = reinterpret_cast<char*>(&test_elem[0]); 3407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); 3408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); 3409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); 3410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); 3411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer. 3412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_EQ(0, elem_in0 - elem_start); 3413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_EQ(kIntSize, elem_in1 - elem_start); 3414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_EQ(2 * kIntSize, elem_out - elem_start); 3415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 3417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Find the address of the a1'st entry in the cache, i.e., &a0[a1*12]. 3419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t0, a1, 1); 3420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a1, a1, t0); 3421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t0, a1, 2); 3422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(cache_entry, cache_entry, t0); 3423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if cache matches: Double value is stored in uint32_t[2] array. 3425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, MemOperand(cache_entry, 0)); 3426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t1, MemOperand(cache_entry, 4)); 3427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t2, MemOperand(cache_entry, 8)); 3428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&calculate, ne, a2, Operand(t0)); 3429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&calculate, ne, a3, Operand(t1)); 3430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Cache hit. Load result, cleanup and return. 34313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Counters* counters = masm->isolate()->counters(); 34323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter( 34333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch counters->transcendental_cache_hit(), 1, scratch0, scratch1); 3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (tagged) { 3435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Pop input value from stack and load result into v0. 3436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(1); 3437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, t2); 3438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load result into f4. 3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f4, FieldMemOperand(t2, HeapNumber::kValueOffset)); 3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } // if (CpuFeatures::IsSupported(FPU)) 3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&calculate); 34463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Counters* counters = masm->isolate()->counters(); 34473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter( 34483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch counters->transcendental_cache_miss(), 1, scratch0, scratch1); 3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (tagged) { 3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&invalid_cache); 3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallExternalReference(ExternalReference(RuntimeFunction(), 3452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()), 3453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1, 3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1); 3455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!CpuFeatures::IsSupported(FPU)) UNREACHABLE(); 3457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 3458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label no_update; 3460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip_cache; 3461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call C function to calculate the result and update the cache. 3463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Register a0 holds precalculated cache entry address; preserve 3464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // it on the stack and pop it into register cache_entry after the 3465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // call. 34663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(cache_entry, a2, a3); 3467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateCallCFunction(masm, scratch0); 3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetCFunctionDoubleResult(f4); 3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Try to update the cache. If we cannot allocate a 3471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // heap number, we return the result without updating. 34723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Pop(cache_entry, a2, a3); 3473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t1, Heap::kHeapNumberMapRootIndex); 3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(t2, scratch0, scratch1, t1, &no_update); 3475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f4, FieldMemOperand(t2, HeapNumber::kValueOffset)); 3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, MemOperand(cache_entry, 0 * kPointerSize)); 3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, MemOperand(cache_entry, 1 * kPointerSize)); 3479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t2, MemOperand(cache_entry, 2 * kPointerSize)); 3480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 34813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 3482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, cache_entry); 3483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&invalid_cache); 3485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The cache is invalid. Call runtime which will recreate the 3486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // cache. 3487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t1, Heap::kHeapNumberMapRootIndex); 3488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(a0, scratch0, scratch1, t1, &skip_cache); 3489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f4, FieldMemOperand(a0, HeapNumber::kValueOffset)); 34903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 34913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 34923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(a0); 34933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(RuntimeFunction(), 1); 34943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f4, FieldMemOperand(v0, HeapNumber::kValueOffset)); 3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&skip_cache); 3499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call C function to calculate the result and answer directly 3500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // without updating the cache. 3501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateCallCFunction(masm, scratch0); 3502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetCFunctionDoubleResult(f4); 3503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&no_update); 3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We return the value in f4 without adding it to the cache, but 3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // we cause a scavenging GC so that future allocations will succeed. 35073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 35083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 35093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 35103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate an aligned object larger than a HeapNumber. 35113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(4 * kPointerSize >= HeapNumber::kSize); 35123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(scratch0, Operand(4 * kPointerSize)); 35133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(scratch0); 35143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); 35153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm, 3522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch) { 3523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ra); 3524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ PrepareCallCFunction(2, scratch); 3525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (IsMipsSoftFloatABI) { 35263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(a0, a1, f4); 3527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov_d(f12, f4); 3529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 35303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 35313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Isolate* isolate = masm->isolate(); 3532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (type_) { 3533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case TranscendentalCache::SIN: 3534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CallCFunction( 35353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::math_sin_double_function(isolate), 35363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 0, 1); 3537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case TranscendentalCache::COS: 3539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CallCFunction( 35403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::math_cos_double_function(isolate), 35413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 0, 1); 35423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 35433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case TranscendentalCache::TAN: 35443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::math_tan_double_function(isolate), 35453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 0, 1); 3546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case TranscendentalCache::LOG: 3548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CallCFunction( 35493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::math_log_double_function(isolate), 35503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 0, 1); 3551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 3553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNIMPLEMENTED(); 3554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ pop(ra); 355744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 355844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 355944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 356044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockRuntime::FunctionId TranscendentalCacheStub::RuntimeFunction() { 3561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (type_) { 3562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Add more cases when necessary. 3563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case TranscendentalCache::SIN: return Runtime::kMath_sin; 3564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case TranscendentalCache::COS: return Runtime::kMath_cos; 35653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case TranscendentalCache::TAN: return Runtime::kMath_tan; 3566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case TranscendentalCache::LOG: return Runtime::kMath_log; 3567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 3568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNIMPLEMENTED(); 3569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Runtime::kAbort; 3570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 357144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 357244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 357344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 357444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StackCheckStub::Generate(MacroAssembler* masm) { 3575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallRuntime(Runtime::kStackGuard, 0, 1); 357644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 357744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 357844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 35793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid InterruptStub::Generate(MacroAssembler* masm) { 35803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallRuntime(Runtime::kInterrupt, 0, 1); 35813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 358285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 358385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 35843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MathPowStub::Generate(MacroAssembler* masm) { 35853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CpuFeatures::Scope fpu_scope(FPU); 35863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Register base = a1; 35873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Register exponent = a2; 35883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Register heapnumbermap = t1; 35893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Register heapnumber = v0; 35903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const DoubleRegister double_base = f2; 35913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const DoubleRegister double_exponent = f4; 35923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const DoubleRegister double_result = f0; 35933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const DoubleRegister double_scratch = f6; 35943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const FPURegister single_scratch = f8; 35953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Register scratch = t5; 35963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Register scratch2 = t3; 35973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 35983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label call_runtime, done, int_exponent; 35993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (exponent_type_ == ON_STACK) { 36003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label base_is_smi, unpack_exponent; 36013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The exponent and base are supplied as arguments on the stack. 36023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This can only happen if the stub is called from non-optimized code. 36033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load input parameters from stack to double registers. 3604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(base, MemOperand(sp, 1 * kPointerSize)); 3605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(exponent, MemOperand(sp, 0 * kPointerSize)); 3606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 36073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); 3608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 36093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); 3610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch, FieldMemOperand(base, JSObject::kMapOffset)); 3611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); 36123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); 36143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&unpack_exponent); 3615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 36163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&base_is_smi); 36173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mtc1(scratch, single_scratch); 36183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cvt_d_w(double_base, single_scratch); 36193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&unpack_exponent); 36203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 3622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); 3624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); 3625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(double_exponent, 3626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(exponent, HeapNumber::kValueOffset)); 36273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (exponent_type_ == TAGGED) { 36283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Base is already in double_base. 36293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 36303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldc1(double_exponent, 36323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(exponent, HeapNumber::kValueOffset)); 36333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 36343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (exponent_type_ != INTEGER) { 36363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label int_exponent_convert; 36373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Detect integer exponents stored as double. 36383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ EmitFPUTruncate(kRoundToMinusInf, 36393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch single_scratch, 36403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch double_exponent, 36413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 36423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2, 36433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kCheckForInexactConversion); 36443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // scratch2 == 0 means there was no conversion error. 36453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); 36463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (exponent_type_ == ON_STACK) { 36483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Detect square root case. Crankshaft detects constant +/-0.5 at 36493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compile time and uses DoMathPowHalf instead. We then skip this check 36503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for non-constant cases of +/-0.5 as these hardly occur. 36513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label not_plus_half; 36523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test for 0.5. 36543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(double_scratch, 0.5); 36553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(USE_DELAY_SLOT, 36563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ¬_plus_half, 36573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NULL, 36583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ne, 36593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch double_exponent, 36603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch double_scratch); 36613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // double_scratch can be overwritten in the delay slot. 36623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calculates square root of base. Check for the special case of 36633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). 36643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(double_scratch, -V8_INFINITY); 36653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); 36663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ neg_d(double_result, double_scratch); 36673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Add +0 to convert -0 to +0. 36693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add_d(double_scratch, double_base, kDoubleRegZero); 36703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sqrt_d(double_result, double_scratch); 36713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 36723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_plus_half); 36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(double_scratch, -0.5); 36753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(USE_DELAY_SLOT, 36763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_runtime, 36773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NULL, 36783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ne, 36793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch double_exponent, 36803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch double_scratch); 36813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // double_scratch can be overwritten in the delay slot. 36823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calculates square root of base. Check for the special case of 36833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). 36843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(double_scratch, -V8_INFINITY); 36853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); 36863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(double_result, kDoubleRegZero); 36873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Add +0 to convert -0 to +0. 36893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add_d(double_scratch, double_base, kDoubleRegZero); 36903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(double_result, 1); 36913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sqrt_d(double_scratch, double_scratch); 36923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ div_d(double_result, double_result, double_scratch); 36933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 36943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ra); 36973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 36983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 36993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(0, 2, scratch); 37003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SetCallCDoubleArguments(double_base, double_exponent); 37013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction( 37023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::power_double_double_function(masm->isolate()), 37033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 0, 2); 37043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3705c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ pop(ra); 3706c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ GetCFunctionDoubleResult(double_result); 37073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 37083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&int_exponent_convert); 37103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mfc1(scratch, single_scratch); 37115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 37125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 37133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calculate power with integer exponent. 37143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&int_exponent); 3715c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 37163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get two copies of exponent in the registers scratch and exponent. 37173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (exponent_type_ == INTEGER) { 37183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, exponent); 37193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 37203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Exponent has previously been stored into scratch as untagged integer. 37213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(exponent, scratch); 37223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3723c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov_d(double_scratch, double_base); // Back up base. 37253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(double_result, 1.0); 3726c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get absolute value of exponent. 37283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label positive_exponent; 37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&positive_exponent, ge, scratch, Operand(zero_reg)); 37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Subu(scratch, zero_reg, scratch); 37313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&positive_exponent); 3732c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 37333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label while_true, no_carry, loop_end; 37343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&while_true); 3735c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(scratch2, scratch, 1); 3737c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&no_carry, eq, scratch2, Operand(zero_reg)); 37393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mul_d(double_result, double_result, double_scratch); 37403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&no_carry); 3741592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 37423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sra(scratch, scratch, 1); 3743592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&loop_end, eq, scratch, Operand(zero_reg)); 37453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mul_d(double_scratch, double_scratch, double_scratch); 37463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&while_true); 37483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop_end); 37503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&done, ge, exponent, Operand(zero_reg)); 37523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(double_scratch, 1.0); 37533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ div_d(double_result, double_scratch, double_result); 37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test whether result is zero. Bail out to check for subnormal result. 37553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. 37563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); 37573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // double_exponent may not contain the exponent value if the input was a 37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // smi. We set it with exponent value before bailing out. 37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mtc1(exponent, single_scratch); 37613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cvt_d_w(double_exponent, single_scratch); 37623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Returning or bailing out. 37643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Counters* counters = masm->isolate()->counters(); 37653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (exponent_type_ == ON_STACK) { 37663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The arguments are still on the stack. 37673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&call_runtime); 37683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); 37693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The stub is called from non-optimized code, which expects the result 37713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // as heap number in exponent. 37723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 37733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateHeapNumber( 37743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); 37753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sdc1(double_result, 37763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); 37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(heapnumber.is(v0)); 37783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); 37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(2); 37803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 37813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(ra); 37823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 37833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(0, 2, scratch); 37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SetCallCDoubleArguments(double_base, double_exponent); 37863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction( 37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::power_double_double_function(masm->isolate()), 37883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 0, 2); 37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(ra); 37913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ GetCFunctionDoubleResult(double_result); 37923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 37943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); 37953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 37963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 37983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool CEntryStub::NeedsImmovableCode() { 38013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 38023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 38033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool CEntryStub::IsPregenerated() { 38063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return (!save_doubles_ || ISOLATE->fp_stubs_generated()) && 38073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result_size_ == 1; 38083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 38093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CodeStub::GenerateStubsAheadOfTime() { 38123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CEntryStub::GenerateAheadOfTime(); 38133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(); 38143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(); 38153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWriteStub::GenerateFixedRegStubsAheadOfTime(); 38163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 38173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CodeStub::GenerateFPStubs() { 38203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CEntryStub save_doubles(1, kSaveFPRegs); 38213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = save_doubles.GetCode(); 38223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch code->set_is_pregenerated(true); 38233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StoreBufferOverflowStub stub(kSaveFPRegs); 38243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub.GetCode()->set_is_pregenerated(true); 38253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch code->GetIsolate()->set_fp_stubs_generated(true); 38263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 38273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CEntryStub::GenerateAheadOfTime() { 38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CEntryStub stub(1, kDontSaveFPRegs); 38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = stub.GetCode(); 38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch code->set_is_pregenerated(true); 38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CEntryStub::GenerateCore(MacroAssembler* masm, 38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* throw_normal_exception, 38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* throw_termination_exception, 38393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* throw_out_of_memory_exception, 384044f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool do_gc, 384144f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool always_allocate) { 3842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v0: result parameter for PerformGC, if any 3843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // s0: number of arguments including receiver (C callee-saved) 3844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // s1: pointer to the first argument (C callee-saved) 3845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // s2: pointer to builtin function (C callee-saved) 3846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 38473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Isolate* isolate = masm->isolate(); 38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (do_gc) { 3850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Move result passed in v0 into a0 to call PerformGC. 3851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(a0, v0); 38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(1, 0, a1); 38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::perform_gc_function(isolate), 1, 0); 3854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference scope_depth = 38573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::heap_always_allocate_scope_depth(isolate); 3858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (always_allocate) { 3859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a0, Operand(scope_depth)); 3860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(a0)); 3861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a1, a1, Operand(1)); 3862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, MemOperand(a0)); 3863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 38653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Prepare arguments for C routine. 38663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a0 = argc 3867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(a0, s0); 38683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1 = argv (set in the delay slot after find_ra below). 3869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We 3871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // also need to reserve the 4 argument slots on the stack. 3872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AssertStackIsAligned(); 3874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a2, Operand(ExternalReference::isolate_address())); 3876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 38773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // To let the GC traverse the return address of the exit frames, we need to 38783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // know where the return address is. The CEntryStub is unmovable, so 38793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // we can store the address on the stack to be able to find it again and 38803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // we never have to restore it, because it will not change. 3881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); 3882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This branch-and-link sequence is needed to find the current PC on mips, 3883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // saved to the ra register. 3884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use masm-> here instead of the double-underscore macro since extra 3885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // coverage code can interfere with the proper calculation of ra. 3886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label find_ra; 3887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->bal(&find_ra); // bal exposes branch delay slot. 38883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->mov(a1, s1); 3889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->bind(&find_ra); 3890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Adjust the value in ra to point to the correct return location, 2nd 3892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // instruction past the real call into C code (the jalr(t9)), and push it. 3893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This is the return address of the exit frame. 38943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int kNumInstructionsToJump = 5; 3895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->Addu(ra, ra, kNumInstructionsToJump * kPointerSize); 3896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->sw(ra, MemOperand(sp)); // This spot was reserved in EnterExitFrame. 38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Stack space reservation moved to the branch delay slot below. 3898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stack is still aligned. 3899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call the C routine. 3901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->mov(t9, s2); // Function pointer to t9 to conform to ABI for PIC. 3902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->jalr(t9); 39033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up sp in the delay slot. 39043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->addiu(sp, sp, -kCArgsSlotsSize); 3905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure the stored 'ra' points to this position. 3906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(kNumInstructionsToJump, 3907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->InstructionsGeneratedSince(&find_ra)); 3908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (always_allocate) { 3911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // It's okay to clobber a2 and a3 here. v0 & v1 contain result. 3912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a2, Operand(scope_depth)); 3913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, MemOperand(a2)); 3914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(a3, a3, Operand(1)); 3915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, MemOperand(a2)); 3916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for failure result. 3919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label failure_returned; 3920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); 3921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(a2, v0, 1); 3922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ andi(t0, a2, kFailureTagMask); 39233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(USE_DELAY_SLOT, &failure_returned, eq, t0, Operand(zero_reg)); 39243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore stack (remove arg slots) in branch delay slot. 39253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addiu(sp, sp, kCArgsSlotsSize); 39263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Exit C frame and return. 3929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v0:v1: result 3930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp: stack pointer 3931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // fp: frame pointer 39323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LeaveExitFrame(save_doubles_, s0, true); 3933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if we should retry or throw exception. 3935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label retry; 3936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&failure_returned); 3937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); 3938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ andi(t0, v0, ((1 << kFailureTypeTagSize) - 1) << kFailureTagSize); 3939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&retry, eq, t0, Operand(zero_reg)); 3940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Special handling of out of memory exceptions. 3942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Failure* out_of_memory = Failure::OutOfMemoryException(); 39433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(USE_DELAY_SLOT, 39443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch throw_out_of_memory_exception, 39453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eq, 39463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch v0, 39473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(reinterpret_cast<int32_t>(out_of_memory))); 39483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If we throw the OOM exception, the value of a3 doesn't matter. 39493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Any instruction can be in the delay slot that's not a jump. 3950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Retrieve the pending exception and clear the variable. 39523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(a3, Heap::kTheHoleValueRootIndex); 3953589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 39543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate))); 3955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, MemOperand(t0)); 3956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, MemOperand(t0)); 3957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Special handling of termination exceptions which are uncatchable 3959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // by javascript code. 39603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(t0, Heap::kTerminationExceptionRootIndex); 39613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(throw_termination_exception, eq, v0, Operand(t0)); 3962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle normal exception. 3964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(throw_normal_exception); 3965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&retry); 3967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Last failure (v0) will be moved to (a0) for parameter when retrying. 396844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 396944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 397044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 397144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid CEntryStub::Generate(MacroAssembler* masm) { 3972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Called from JavaScript; parameters are on stack as if calling JS function 39733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // s0: number of arguments including receiver 39743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // s1: size of arguments excluding receiver 39753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // s2: pointer to builtin function 3976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // fp: frame pointer (restored after C call) 3977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp: stack pointer (restored as callee's sp after C call) 3978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // cp: current context (C callee-saved) 3979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // NOTE: Invocations of builtins may return failure objects 3981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // instead of a proper result. The builtin entry handles 3982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // this by performing a garbage collection and retrying the 3983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // builtin once. 3984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 39853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // NOTE: s0-s2 hold the arguments of this function instead of a0-a2. 39863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The reason for this is that these arguments would need to be saved anyway 39873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // so it's faster to set them up directly. 39883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // See MacroAssembler::PrepareCEntryArgs and PrepareCEntryFunction. 39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute the argv pointer in a callee-saved register. 3991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(s1, sp, s1); 3992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Enter the exit frame that transitions from JavaScript to C++. 39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 3995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ EnterExitFrame(save_doubles_); 3996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // s0: number of arguments (C callee-saved) 3998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // s1: pointer to first argument (C callee-saved) 3999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // s2: pointer to builtin function (C callee-saved) 4000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label throw_normal_exception; 4002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label throw_termination_exception; 4003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label throw_out_of_memory_exception; 4004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call into the runtime system. 4006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateCore(masm, 4007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &throw_normal_exception, 4008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &throw_termination_exception, 4009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &throw_out_of_memory_exception, 4010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch false, 4011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch false); 4012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do space-specific GC and retry runtime call. 4014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateCore(masm, 4015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &throw_normal_exception, 4016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &throw_termination_exception, 4017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &throw_out_of_memory_exception, 4018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch true, 4019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch false); 4020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do full GC and retry runtime call one final time. 4022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Failure* failure = Failure::InternalError(); 4023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(reinterpret_cast<int32_t>(failure))); 4024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateCore(masm, 4025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &throw_normal_exception, 4026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &throw_termination_exception, 4027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &throw_out_of_memory_exception, 4028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch true, 4029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch true); 4030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&throw_out_of_memory_exception); 40323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set external caught exception to false. 40333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Isolate* isolate = masm->isolate(); 40343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, 40353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate); 40363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a0, Operand(false, RelocInfo::NONE)); 40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a2, Operand(external_caught)); 40383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a0, MemOperand(a2)); 40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set pending exception and v0 to out of memory exception. 40413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Failure* out_of_memory = Failure::OutOfMemoryException(); 40423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(v0, Operand(reinterpret_cast<int32_t>(out_of_memory))); 40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 40443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate))); 40453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(v0, MemOperand(a2)); 40463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fall through to the next label. 4047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&throw_termination_exception); 40493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ThrowUncatchable(v0); 4050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&throw_normal_exception); 40523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Throw(v0); 405344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 405444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 405544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 405644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { 40573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label invoke, handler_entry, exit; 40583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Isolate* isolate = masm->isolate(); 4059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers: 4061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: entry address 4062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: function 40633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a2: receiver 4064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: argc 4065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 4066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stack: 4067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 4 args slots 4068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // args 4069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Save callee saved registers on the stack. 407169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ MultiPush(kCalleeSaved | ra.bit()); 4072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4073589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 4074589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CpuFeatures::Scope scope(FPU); 4075589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Save callee-saved FPU registers. 4076589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ MultiPushFPU(kCalleeSavedFPU); 40773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the reserved register for 0.0. 40783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(kDoubleRegZero, 0.0); 4079589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 4080589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 40813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load argv in s0 register. 4083589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize; 4084589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 4085589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch offset_to_argv += kNumCalleeSavedFPU * kDoubleSize; 4086589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 4087589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 40883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InitializeRootRegister(); 4089589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ lw(s0, MemOperand(sp, offset_to_argv + kCArgsSlotsSize)); 4090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We build an EntryFrame. 4092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t3, Operand(-1)); // Push a bad frame pointer to fail if it is used. 4093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 4094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t2, Operand(Smi::FromInt(marker))); 4095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t1, Operand(Smi::FromInt(marker))); 4096589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ li(t0, Operand(ExternalReference(Isolate::kCEntryFPAddress, 40973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate))); 4098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, MemOperand(t0)); 4099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(t3, t2, t1, t0); 41003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up frame pointer for the frame to be pushed. 4101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(fp, sp, -EntryFrameConstants::kCallerFPOffset); 4102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers: 4104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: entry_address 4105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: function 41063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a2: receiver_pointer 4107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: argc 4108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // s0: argv 4109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 4110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stack: 4111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // caller fp | 4112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // function slot | entry frame 4113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // context slot | 4114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // bad fp (0xff...f) | 4115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // callee saved registers + ra 4116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 4 args slots 4117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // args 4118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 41193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If this is the outermost JS call, set js_entry_sp value. 41203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label non_outermost_js; 41213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate); 41223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ li(t1, Operand(ExternalReference(js_entry_sp))); 41233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(t2, MemOperand(t1)); 41243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(&non_outermost_js, ne, t2, Operand(zero_reg)); 41253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(fp, MemOperand(t1)); 41263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ li(t0, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); 41273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label cont; 41283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(&cont); 41293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ nop(); // Branch delay slot nop. 41303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&non_outermost_js); 41313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ li(t0, Operand(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME))); 41323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&cont); 41333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ push(t0); 4134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 41353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Jump to a faked try block that does the invoke, with a faked catch 41363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // block that sets the pending exception. 41373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&invoke); 41383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&handler_entry); 41393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch handler_offset_ = handler_entry.pos(); 41403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Caught exception: Store result (exception) in the pending exception 41413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // field in the JSEnv and return a failure sentinel. Coming in here the 41423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // fp will be invalid because the PushTryHandler below sets it to 0 to 41433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // signal the existence of the JSEntry frame. 4144589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 41453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate))); 4146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(v0, MemOperand(t0)); // We come back from 'invoke'. result is in v0. 4147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(reinterpret_cast<int32_t>(Failure::Exception()))); 4148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(&exit); // b exposes branch delay slot. 4149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ nop(); // Branch delay slot nop. 4150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 41513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke: Link this frame into the handler chain. There's only one 41523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // handler block in this code object, so its index is 0. 4153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&invoke); 41543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushTryHandler(StackHandler::JS_ENTRY, 0); 4155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If an exception not caught by another handler occurs, this handler 4156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // returns control to the code after the bal(&invoke) above, which 4157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // restores all kCalleeSaved registers (including cp and fp) to their 4158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // saved values before returning a failure to C. 4159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Clear any pending exceptions. 41613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); 4162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 41633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate))); 4164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t1, MemOperand(t0)); 4165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Invoke the function by calling through JS entry trampoline builtin. 4167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Notice that we cannot store a reference to the trampoline code directly in 4168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // this stub, because runtime stubs are not traversed when doing GC. 4169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers: 4171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: entry_address 4172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: function 41733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a2: receiver_pointer 4174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: argc 4175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // s0: argv 4176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 4177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stack: 4178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // handler frame 4179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // entry frame 4180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // callee saved registers + ra 4181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 4 args slots 4182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // args 4183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_construct) { 4185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline, 41863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate); 4187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t0, Operand(construct_entry)); 4188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 4189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference entry(Builtins::kJSEntryTrampoline, masm->isolate()); 4190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t0, Operand(entry)); 4191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t9, MemOperand(t0)); // Deref address. 4193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call JSEntryTrampoline. 4195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag); 4196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Call(t9); 4197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Unlink this frame from the handler chain. 4199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ PopTryHandler(); 4200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&exit); // v0 holds result 42023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if the current stack frame is marked as the outermost JS frame. 42033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label non_outermost_js_2; 42043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ pop(t1); 42053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&non_outermost_js_2, 42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ne, 42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch t1, 42083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); 42093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ li(t1, Operand(ExternalReference(js_entry_sp))); 42103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(zero_reg, MemOperand(t1)); 42113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&non_outermost_js_2); 4212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore the top frame descriptors from the stack. 4214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ pop(t1); 4215589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ li(t0, Operand(ExternalReference(Isolate::kCEntryFPAddress, 42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate))); 4217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t1, MemOperand(t0)); 4218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Reset the stack to the callee saved registers. 4220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset); 4221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4222589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 4223589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CpuFeatures::Scope scope(FPU); 4224589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Restore callee-saved fpu registers. 4225589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ MultiPopFPU(kCalleeSavedFPU); 4226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 4227589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 4228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore callee saved registers from the stack. 422969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ MultiPop(kCalleeSaved | ra.bit()); 4230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return. 4231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ra); 423244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 423344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 423444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Uses registers a0 to t0. 4236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Expected input (depending on whether args are in registers or on the stack): 4237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// * object: a0 or at sp + 1 * kPointerSize. 4238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// * function: a1 or at sp. 4239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// 42403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// An inlined call site may have been generated before calling this stub. 42413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// In this case the offset to the inline site to patch is passed on the stack, 42423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// in the safepoint slot for register t0. 424344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid InstanceofStub::Generate(MacroAssembler* masm) { 4244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call site inlining and patching implies arguments in registers. 4245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck()); 4246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ReturnTrueFalse is only implemented for inlined call sites. 4247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!ReturnTrueFalseObject() || HasCallSiteInlineCheck()); 4248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fixed register usage throughout the stub: 4250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Register object = a0; // Object (lhs). 4251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register map = a3; // Map of the object. 4252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Register function = a1; // Function (rhs). 4253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Register prototype = t0; // Prototype of the function. 4254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Register inline_site = t5; 4255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Register scratch = a2; 4256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int32_t kDeltaToLoadBoolResult = 5 * kPointerSize; 42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow, loop, is_instance, is_not_instance, not_js_object; 4260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!HasArgsInRegisters()) { 4262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(object, MemOperand(sp, 1 * kPointerSize)); 4263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(function, MemOperand(sp, 0)); 4264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the left hand is a JS object and load map. 4267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(object, ¬_js_object); 4268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); 4269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If there is a call site cache don't look in the global cache, but do the 4271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // real lookup and update the call site cache. 4272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!HasCallSiteInlineCheck()) { 4273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, Heap::kInstanceofCacheFunctionRootIndex); 42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, function, Operand(at)); 42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, Heap::kInstanceofCacheMapRootIndex); 42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, map, Operand(at)); 4278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); 4279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 4280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 4282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the prototype of the function. 42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); 4286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the function prototype is a JS object. 4288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(prototype, &slow); 4289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); 4290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Update the global instanceof or call site inlined cache with the current 4292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // map and function. The cached answer will be set when it is known below. 4293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!HasCallSiteInlineCheck()) { 4294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 4295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); 4296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(HasArgsInRegisters()); 42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Patch the (relocated) inlined map check. 42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The offset was stored in t0 safepoint slot. 43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal). 43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadFromSafepointRegisterSlot(scratch, t0); 43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Subu(inline_site, ra, scratch); 43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the map location in scratch and patch it. 43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ GetRelocatedValue(inline_site, scratch, v1); // v1 used as scratch. 43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(map, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); 4307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Register mapping: a3 is object map and t0 is function prototype. 4310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get prototype of object into a2. 4311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch, FieldMemOperand(map, Map::kPrototypeOffset)); 4312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We don't need map any more. Use it as a scratch register. 4314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2 = map; 4315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch map = no_reg; 4316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Loop through the prototype chain looking for the function prototype. 4318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(scratch2, Heap::kNullValueRootIndex); 4319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&loop); 4320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&is_instance, eq, scratch, Operand(prototype)); 4321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&is_not_instance, eq, scratch, Operand(scratch2)); 4322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset)); 4323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset)); 4324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&loop); 4325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&is_instance); 4327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(Smi::FromInt(0) == 0); 4328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!HasCallSiteInlineCheck()) { 4329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, zero_reg); 4330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); 4331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 43323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Patch the call site to return true. 43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(v0, Heap::kTrueValueRootIndex); 43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(inline_site, inline_site, Operand(kDeltaToLoadBoolResult)); 43353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the boolean result location in scratch and patch it. 43363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PatchRelocatedValue(inline_site, scratch, v0); 43373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!ReturnTrueFalseObject()) { 43393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(Smi::FromInt(0), 0); 43403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(v0, zero_reg); 43413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 4344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&is_not_instance); 4346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!HasCallSiteInlineCheck()) { 4347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(Smi::FromInt(1))); 4348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); 4349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 43503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Patch the call site to return false. 43513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(v0, Heap::kFalseValueRootIndex); 43523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(inline_site, inline_site, Operand(kDeltaToLoadBoolResult)); 43533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the boolean result location in scratch and patch it. 43543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PatchRelocatedValue(inline_site, scratch, v0); 43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!ReturnTrueFalseObject()) { 43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(v0, Operand(Smi::FromInt(1))); 43583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 43603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 4362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label object_not_null, object_not_null_or_smi; 4364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_js_object); 4365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Before null, smi and string value checks, check that the rhs is a function 4366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // as for a non-function rhs an exception needs to be thrown. 4367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(function, &slow); 4368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(function, scratch2, scratch); 4369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&slow, ne, scratch, Operand(JS_FUNCTION_TYPE)); 4370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Null is not instance of anything. 43723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&object_not_null, 43733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ne, 43743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 43753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(masm->isolate()->factory()->null_value())); 4376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(Smi::FromInt(1))); 4377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 4378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&object_not_null); 4380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Smi values are not instances of anything. 4381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(object, &object_not_null_or_smi); 4382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(Smi::FromInt(1))); 4383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 4384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&object_not_null_or_smi); 4386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // String values are not instances of anything. 4387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IsObjectJSStringType(object, scratch, &slow); 4388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(Smi::FromInt(1))); 4389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 4390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Slow-case. Tail call builtin. 4392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 4393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!ReturnTrueFalseObject()) { 4394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasArgsInRegisters()) { 4395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(a0, a1); 4396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 4398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 44013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(a0, a1); 44023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); 44033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(a0, v0); 4405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(v0, Heap::kTrueValueRootIndex); 4406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DropAndRet(HasArgsInRegisters() ? 0 : 2, eq, a0, Operand(zero_reg)); 4407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(v0, Heap::kFalseValueRootIndex); 4408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DropAndRet(HasArgsInRegisters() ? 0 : 2); 4409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 441044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 441144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 441244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochRegister InstanceofStub::left() { return a0; } 4414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochRegister InstanceofStub::right() { return a1; } 4417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 441944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 4420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The displacement is the offset of the last parameter (if any) 4421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // relative to the frame pointer. 4422db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kDisplacement = 4423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StandardFrameConstants::kCallerSPOffset - kPointerSize; 4424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smiGenerateReadElement. 4426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow; 4427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(a1, &slow); 4428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the calling frame is an arguments adaptor frame. 4430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label adaptor; 4431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 4432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); 4433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&adaptor, 4434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch eq, 4435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a3, 4436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 4437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check index (a1) against formal parameters count limit passed in 4439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // through register a0. Use unsigned comparison to get negative 4440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // check for free. 4441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&slow, hs, a1, Operand(a0)); 4442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Read the argument from the stack and return it. 4444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(a3, a0, a1); 4445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t3, a3, kPointerSizeLog2 - kSmiTagSize); 4446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a3, fp, Operand(t3)); 4447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, MemOperand(a3, kDisplacement)); 4448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 4449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Arguments adaptor case: Check index (a1) against actual arguments 4451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // limit found in the arguments adaptor frame. Use unsigned 4452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // comparison to get negative check for free. 4453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&adaptor); 4454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 4455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&slow, Ugreater_equal, a1, Operand(a0)); 4456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Read the argument from the adaptor frame and return it. 4458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(a3, a0, a1); 4459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t3, a3, kPointerSizeLog2 - kSmiTagSize); 4460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a3, a2, Operand(t3)); 4461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, MemOperand(a3, kDisplacement)); 4462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 4463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Slow-case: Handle non-smi or out-of-bounds access to arguments 4465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // by calling the runtime system. 4466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 4467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(a1); 4468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); 446944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 447044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 447144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 44723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) { 4473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[0] : number of parameters 4474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[4] : receiver displacement 4475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[8] : function 44763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if the calling frame is an arguments adaptor frame. 44773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label runtime; 44783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 44793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(a2, MemOperand(a3, StandardFrameConstants::kContextOffset)); 44803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&runtime, 44813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ne, 44823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a2, 44833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 44843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 44853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Patch the arguments.length and the parameters pointer in the current frame. 44863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset)); 44873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(a2, MemOperand(sp, 0 * kPointerSize)); 44883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sll(t3, a2, 1); 44893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(a3, a3, Operand(t3)); 44903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ addiu(a3, a3, StandardFrameConstants::kCallerSPOffset); 44913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(a3, MemOperand(sp, 1 * kPointerSize)); 44923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 44933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&runtime); 44943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 44953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 44963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 44973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 44983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { 44993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Stack layout: 45003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // sp[0] : number of parameters (tagged) 45013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // sp[4] : address of receiver argument 45023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // sp[8] : function 45033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Registers used over whole function: 45043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // t2 : allocated object (tagged) 45053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // t5 : mapped parameter count (tagged) 45063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(a1, MemOperand(sp, 0 * kPointerSize)); 45083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a1 = parameter count (tagged) 45093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if the calling frame is an arguments adaptor frame. 45113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label runtime; 45123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label adaptor_frame, try_allocate; 45133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 45143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(a2, MemOperand(a3, StandardFrameConstants::kContextOffset)); 45153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&adaptor_frame, 45163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eq, 45173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a2, 45183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 45193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // No adaptor, parameter count = argument count. 45213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(a2, a1); 45223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(&try_allocate); 45233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ nop(); // Branch delay slot nop. 45243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We have an adaptor frame. Patch the parameters pointer. 45263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&adaptor_frame); 45273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset)); 45283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sll(t6, a2, 1); 45293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(a3, a3, Operand(t6)); 45303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset)); 45313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(a3, MemOperand(sp, 1 * kPointerSize)); 45323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a1 = parameter count (tagged) 45343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a2 = argument count (tagged) 45353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compute the mapped parameter count = min(a1, a2) in a1. 45363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label skip_min; 45373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(&skip_min, lt, a1, Operand(a2)); 45383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(a1, a2); 45393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&skip_min); 4540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 45413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&try_allocate); 45423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compute the sizes of backing store, parameter map, and arguments object. 45443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 1. Parameter map, has 2 extra words containing context and backing store. 45453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kParameterMapHeaderSize = 45463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedArray::kHeaderSize + 2 * kPointerSize; 45473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If there are no mapped parameters, we do not need the parameter_map. 45483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label param_map_size; 45493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT_EQ(0, Smi::FromInt(0)); 45503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(USE_DELAY_SLOT, ¶m_map_size, eq, a1, Operand(zero_reg)); 45513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(t5, zero_reg); // In delay slot: param map size = 0 when a1 == 0. 45523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sll(t5, a1, 1); 45533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ addiu(t5, t5, kParameterMapHeaderSize); 45543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(¶m_map_size); 45553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 2. Backing store. 45573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sll(t6, a2, 1); 45583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t5, t5, Operand(t6)); 45593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t5, t5, Operand(FixedArray::kHeaderSize)); 45603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 3. Arguments object. 45623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t5, t5, Operand(Heap::kArgumentsObjectSize)); 45633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Do the allocation of all three objects in one go. 45653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AllocateInNewSpace(t5, v0, a3, t0, &runtime, TAG_OBJECT); 45663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // v0 = address of new object(s) (tagged) 45683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a2 = argument count (tagged) 45693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the arguments boilerplate from the current (global) context into t0. 45703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kNormalOffset = 45713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX); 45723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kAliasedOffset = 45733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX); 45743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 45763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(t0, FieldMemOperand(t0, GlobalObject::kGlobalContextOffset)); 45773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label skip2_ne, skip2_eq; 45783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(&skip2_ne, ne, a1, Operand(zero_reg)); 45793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(t0, MemOperand(t0, kNormalOffset)); 45803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&skip2_ne); 45813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(&skip2_eq, eq, a1, Operand(zero_reg)); 45833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(t0, MemOperand(t0, kAliasedOffset)); 45843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&skip2_eq); 45853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // v0 = address of new object (tagged) 45873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a1 = mapped parameter count (tagged) 45883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a2 = argument count (tagged) 45893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // t0 = address of boilerplate object (tagged) 45903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Copy the JS object part. 45913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { 45923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(a3, FieldMemOperand(t0, i)); 45933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(a3, FieldMemOperand(v0, i)); 45943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 45953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the callee in-object property. 45973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); 45983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(a3, MemOperand(sp, 2 * kPointerSize)); 45993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kCalleeOffset = JSObject::kHeaderSize + 46003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Heap::kArgumentsCalleeIndex * kPointerSize; 46013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(a3, FieldMemOperand(v0, kCalleeOffset)); 46023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Use the length (smi tagged) and set that as an in-object property too. 46043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 46053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kLengthOffset = JSObject::kHeaderSize + 46063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Heap::kArgumentsLengthIndex * kPointerSize; 46073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(a2, FieldMemOperand(v0, kLengthOffset)); 46083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the elements pointer in the allocated arguments object. 46103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If we allocated a parameter map, t0 will point there, otherwise 46113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // it will point to the backing store. 46123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t0, v0, Operand(Heap::kArgumentsObjectSize)); 46133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset)); 46143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // v0 = address of new object (tagged) 46163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a1 = mapped parameter count (tagged) 46173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a2 = argument count (tagged) 46183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // t0 = address of parameter map or backing store (tagged) 46193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Initialize parameter map. If there are no mapped arguments, we're done. 46203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label skip_parameter_map; 46213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label skip3; 46223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(&skip3, ne, a1, Operand(Smi::FromInt(0))); 46233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Move backing store address to a3, because it is 46243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // expected there when filling in the unmapped arguments. 46253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(a3, t0); 46263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&skip3); 46273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(&skip_parameter_map, eq, a1, Operand(Smi::FromInt(0))); 46293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadRoot(t2, Heap::kNonStrictArgumentsElementsMapRootIndex); 46313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(t2, FieldMemOperand(t0, FixedArray::kMapOffset)); 46323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t2, a1, Operand(Smi::FromInt(2))); 46333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(t2, FieldMemOperand(t0, FixedArray::kLengthOffset)); 46343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(cp, FieldMemOperand(t0, FixedArray::kHeaderSize + 0 * kPointerSize)); 46353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sll(t6, a1, 1); 46363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t2, t0, Operand(t6)); 46373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t2, t2, Operand(kParameterMapHeaderSize)); 46383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(t2, FieldMemOperand(t0, FixedArray::kHeaderSize + 1 * kPointerSize)); 46393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Copy the parameter slots and the holes in the arguments. 46413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We need to fill in mapped_parameter_count slots. They index the context, 46423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // where parameters are stored in reverse order, at 46433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 46443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // The mapped parameter thus need to get indices 46453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // MIN_CONTEXT_SLOTS+parameter_count-1 .. 46463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count 46473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We loop from right to left. 46483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label parameters_loop, parameters_test; 46493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(t2, a1); 46503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(t5, MemOperand(sp, 0 * kPointerSize)); 46513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t5, t5, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); 46523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Subu(t5, t5, Operand(a1)); 46533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadRoot(t3, Heap::kTheHoleValueRootIndex); 46543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sll(t6, t2, 1); 46553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(a3, t0, Operand(t6)); 46563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(a3, a3, Operand(kParameterMapHeaderSize)); 46573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // t2 = loop variable (tagged) 46593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a1 = mapping index (tagged) 46603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a3 = address of backing store (tagged) 46613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // t0 = address of parameter map (tagged) 46623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // t1 = temporary scratch (a.o., for address calculation) 46633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // t3 = the hole value 46643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(¶meters_test); 46653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(¶meters_loop); 46673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Subu(t2, t2, Operand(Smi::FromInt(1))); 46683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sll(t1, t2, 1); 46693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t1, t1, Operand(kParameterMapHeaderSize - kHeapObjectTag)); 46703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t6, t0, t1); 46713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(t5, MemOperand(t6)); 46723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Subu(t1, t1, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); 46733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t6, a3, t1); 46743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(t3, MemOperand(t6)); 46753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t5, t5, Operand(Smi::FromInt(1))); 46763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(¶meters_test); 46773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(¶meters_loop, ne, t2, Operand(Smi::FromInt(0))); 46783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&skip_parameter_map); 46803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a2 = argument count (tagged) 46813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a3 = address of backing store (tagged) 46823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // t1 = scratch 46833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Copy arguments header and remaining slots (if there are any). 46843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadRoot(t1, Heap::kFixedArrayMapRootIndex); 46853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(t1, FieldMemOperand(a3, FixedArray::kMapOffset)); 46863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(a2, FieldMemOperand(a3, FixedArray::kLengthOffset)); 46873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label arguments_loop, arguments_test; 46893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(t5, a1); 46903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(t0, MemOperand(sp, 1 * kPointerSize)); 46913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sll(t6, t5, 1); 46923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Subu(t0, t0, Operand(t6)); 46933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(&arguments_test); 46943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&arguments_loop); 46963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Subu(t0, t0, Operand(kPointerSize)); 46973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(t2, MemOperand(t0, 0)); 46983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sll(t6, t5, 1); 46993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t1, a3, Operand(t6)); 47003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(t2, FieldMemOperand(t1, FixedArray::kHeaderSize)); 47013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t5, t5, Operand(Smi::FromInt(1))); 47023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&arguments_test); 47043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(&arguments_loop, lt, t5, Operand(a2)); 47053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Return and remove the on-stack parameters. 47073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(3); 47083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Do the runtime call to allocate the arguments object. 47103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a2 = argument count (tagged) 47113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&runtime); 47123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(a2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count. 47133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 47143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 47153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { 47183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // sp[0] : number of parameters 47193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // sp[4] : receiver displacement 47203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // sp[8] : function 4721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the calling frame is an arguments adaptor frame. 4722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label adaptor_frame, try_allocate, runtime; 4723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 4724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); 4725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&adaptor_frame, 4726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch eq, 4727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a3, 4728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 4729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the length from the frame. 4731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, 0)); 4732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&try_allocate); 4733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Patch the arguments.length and the parameters pointer. 4735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&adaptor_frame); 4736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 4737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, MemOperand(sp, 0)); 4738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(at, a1, kPointerSizeLog2 - kSmiTagSize); 4739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a3, a2, Operand(at)); 4740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset)); 4742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, MemOperand(sp, 1 * kPointerSize)); 4743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Try the new space allocation. Start out with computing the size 4745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // of the arguments object and the elements array in words. 4746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label add_arguments_object; 4747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&try_allocate); 4748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&add_arguments_object, eq, a1, Operand(zero_reg)); 4749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(a1, a1, kSmiTagSize); 4750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a1, a1, Operand(FixedArray::kHeaderSize / kPointerSize)); 4752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&add_arguments_object); 47533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(a1, a1, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize)); 4754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do the allocation of both objects in one go. 47563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AllocateInNewSpace(a1, 47573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch v0, 47583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch a2, 47593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch a3, 47603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch &runtime, 47613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static_cast<AllocationFlags>(TAG_OBJECT | 47623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SIZE_IN_WORDS)); 4763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the arguments boilerplate from the current (global) context. 4765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 4766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, FieldMemOperand(t0, GlobalObject::kGlobalContextOffset)); 47673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(t0, MemOperand(t0, Context::SlotOffset( 47683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX))); 4769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Copy the JS object part. 4771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CopyFields(v0, t0, a3.bit(), JSObject::kHeaderSize / kPointerSize); 4772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the length (smi tagged) and set that as an in-object property too. 4774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 4775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, 0 * kPointerSize)); 4776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, FieldMemOperand(v0, JSObject::kHeaderSize + 47773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Heap::kArgumentsLengthIndex * kPointerSize)); 4778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 4780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, eq, a1, Operand(zero_reg)); 4781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the parameters pointer from the stack. 4783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, MemOperand(sp, 1 * kPointerSize)); 4784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 47853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the elements pointer in the allocated arguments object and 4786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // initialize the header in the elements fixed array. 47873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(t0, v0, Operand(Heap::kArgumentsObjectSizeStrict)); 4788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset)); 4789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(a3, Heap::kFixedArrayMapRootIndex); 4790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, FieldMemOperand(t0, FixedArray::kMapOffset)); 4791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, FieldMemOperand(t0, FixedArray::kLengthOffset)); 47923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Untag the length for the loop. 47933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ srl(a1, a1, kSmiTagSize); 4794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Copy the fixed array slots. 4796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label loop; 47973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up t0 to point to the first array slot. 4798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t0, t0, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 4799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&loop); 4800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Pre-decrement a2 with kPointerSize on each iteration. 4801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Pre-decrement in order to skip receiver. 4802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a2, a2, Operand(-kPointerSize)); 4803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, MemOperand(a2)); 4804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Post-increment t0 with kPointerSize on each iteration. 4805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, MemOperand(t0)); 4806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t0, t0, Operand(kPointerSize)); 4807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(a1, a1, Operand(1)); 4808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&loop, ne, a1, Operand(zero_reg)); 4809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return and remove the on-stack parameters. 4811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 48123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(3); 4813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do the runtime call to allocate the arguments object. 4815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&runtime); 48163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1); 481744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 481844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 481944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 482044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RegExpExecStub::Generate(MacroAssembler* masm) { 4821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Just jump directly to runtime if native RegExp is not selected at compile 4822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // time or if regexp entry in generated code is turned off runtime switch or 4823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // at compilation. 4824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef V8_INTERPRETED_REGEXP 4825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 4826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else // V8_INTERPRETED_REGEXP 4827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stack frame on entry. 4829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[0]: last_match_info (expected JSArray) 4830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[4]: previous index 4831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[8]: subject string 4832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[12]: JSRegExp object 4833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4834db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kLastMatchInfoOffset = 0 * kPointerSize; 4835db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kPreviousIndexOffset = 1 * kPointerSize; 4836db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kSubjectOffset = 2 * kPointerSize; 4837db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kJSRegExpOffset = 3 * kPointerSize; 4838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 48393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Isolate* isolate = masm->isolate(); 48403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label runtime, invoke_regexp; 4842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocation of registers for this function. These are in callee save 4844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // registers and will be preserved by the call to the native RegExp code, as 4845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // this code is called using the normal C calling convention. When calling 4846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // directly from generated code the native RegExp code will not do a GC and 4847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // therefore the content of these registers are safe to use after the call. 4848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // MIPS - using s0..s2, since we are not using CEntry Stub. 4849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register subject = s0; 4850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register regexp_data = s1; 4851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register last_match_info_elements = s2; 4852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Ensure that a RegExp stack is allocated. 4854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference address_of_regexp_stack_memory_address = 4855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference::address_of_regexp_stack_memory_address( 48563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate); 4857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference address_of_regexp_stack_memory_size = 48583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::address_of_regexp_stack_memory_size(isolate); 4859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a0, Operand(address_of_regexp_stack_memory_size)); 4860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(a0, 0)); 4861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&runtime, eq, a0, Operand(zero_reg)); 4862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the first argument is a JSRegExp object. 4864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(sp, kJSRegExpOffset)); 4865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 4866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a0, &runtime); 4867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a0, a1, a1); 4868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&runtime, ne, a1, Operand(JS_REGEXP_TYPE)); 4869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the RegExp has been compiled (data contains a fixed array). 4871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(regexp_data, FieldMemOperand(a0, JSRegExp::kDataOffset)); 4872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (FLAG_debug_code) { 4873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t0, regexp_data, Operand(kSmiTagMask)); 4874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Check(nz, 4875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "Unexpected type for RegExp data, FixedArray expected", 4876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch t0, 4877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(zero_reg)); 4878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(regexp_data, a0, a0); 4879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Check(eq, 4880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "Unexpected type for RegExp data, FixedArray expected", 4881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a0, 4882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(FIXED_ARRAY_TYPE)); 4883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // regexp_data: RegExp data (FixedArray) 4886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 4887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); 4888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&runtime, ne, a0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); 4889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // regexp_data: RegExp data (FixedArray) 4891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the number of captures fit in the static offsets vector buffer. 4892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, 4893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 4894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate number of capture registers (number_of_captures + 1) * 2. This 4895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // uses the asumption that smis are 2 * their untagged value. 4896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 4897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 4898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a2, a2, Operand(2)); // a2 was a smi. 4899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the static offsets vector buffer is large enough. 4900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&runtime, hi, a2, Operand(OffsetsVector::kStaticOffsetsVectorSize)); 4901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: Number of capture registers 4903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // regexp_data: RegExp data (FixedArray) 4904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the second argument is a string. 4905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(subject, MemOperand(sp, kSubjectOffset)); 4906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(subject, &runtime); 4907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(subject, a0, a0); 4908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a0, a0, Operand(kIsNotStringMask)); 4909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kStringTag == 0); 4910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&runtime, ne, a0, Operand(zero_reg)); 4911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the length of the string to r3. 4913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(subject, String::kLengthOffset)); 4914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: Number of capture registers 4916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: Length of subject string as a smi 4917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // subject: Subject string 4918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // regexp_data: RegExp data (FixedArray) 4919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the third argument is a positive smi less than the subject 4920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // string length. A negative value will be greater (unsigned comparison). 4921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(sp, kPreviousIndexOffset)); 49223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(a0, &runtime); 4923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&runtime, ls, a3, Operand(a0)); 4924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: Number of capture registers 4926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // subject: Subject string 4927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // regexp_data: RegExp data (FixedArray) 4928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the fourth object is a JSArray object. 4929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(sp, kLastMatchInfoOffset)); 4930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a0, &runtime); 4931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a0, a1, a1); 4932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&runtime, ne, a1, Operand(JS_ARRAY_TYPE)); 4933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the JSArray is in fast case. 4934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(last_match_info_elements, 4935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(a0, JSArray::kElementsOffset)); 4936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); 4937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&runtime, ne, a0, Operand( 49383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate->factory()->fixed_array_map())); 4939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the last match info has space for the capture registers and the 4940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // additional information. 4941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, 4942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); 4943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a2, a2, Operand(RegExpImpl::kLastMatchOverhead)); 4944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(at, a0, kSmiTagSize); // Untag length for comparison. 4945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&runtime, gt, a2, Operand(at)); 494669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 494769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Reset offset for possibly sliced string. 494869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(t0, zero_reg); 4949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // subject: Subject string 4950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // regexp_data: RegExp data (FixedArray) 4951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the representation and encoding of the subject string. 4952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label seq_string; 4953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); 4954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 49553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First check for flat string. None of the following string type tests will 49563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // succeed if subject is not a string or a short external string. 49573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(a1, 49583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a0, 49593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(kIsNotStringMask | 49603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kStringRepresentationMask | 49613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kShortExternalStringMask)); 4962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); 496369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Branch(&seq_string, eq, a1, Operand(zero_reg)); 4964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // subject: Subject string 4966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: instance type if Subject string 4967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // regexp_data: RegExp data (FixedArray) 49683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1: whether subject is a string and if yes, its string representation 496969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Check for flat cons string or sliced string. 4970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // A flat cons string is a cons string where the second part is the empty 4971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // string. In that case the subject string is just the first part of the cons 4972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // string. Also in this case the first part of the cons string is known to be 4973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a sequential string or an external string. 497469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // In the case of a sliced string its offset has to be taken into account. 49753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label cons_string, external_string, check_encoding; 497669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kConsStringTag < kExternalStringTag); 497769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 49783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 49793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 498069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Branch(&cons_string, lt, a1, Operand(kExternalStringTag)); 49813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&external_string, eq, a1, Operand(kExternalStringTag)); 49823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Catch non-string subject or short external string. 49843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); 49853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask)); 49863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&runtime, ne, at, Operand(zero_reg)); 498769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 498869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // String is sliced. 498969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset)); 499069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ sra(t0, t0, kSmiTagSize); 499169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); 499269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // t5: offset of sliced string, smi-tagged. 499369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(&check_encoding); 499469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // String is a cons string, check whether it is flat. 499569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&cons_string); 4996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset)); 4997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(a1, Heap::kEmptyStringRootIndex); 4998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&runtime, ne, a0, Operand(a1)); 4999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); 500069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Is first part of cons or parent of slice a flat string? 500169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&check_encoding); 5002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); 5003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 5004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSeqStringTag == 0); 5005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(at, a0, Operand(kStringRepresentationMask)); 50063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&external_string, ne, at, Operand(zero_reg)); 5007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&seq_string); 5009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // subject: Subject string 5010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // regexp_data: RegExp data (FixedArray) 5011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: Instance type of subject string 5012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kStringEncodingMask == 4); 5013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kAsciiStringTag == 4); 5014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kTwoByteStringTag == 0); 5015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Find the code object based on the assumptions above. 50163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ASCII. 5017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset)); 50183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sra(a3, a0, 2); // a3 is 1 for ASCII, 0 for UC16 (used below). 501969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); 50203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. 5021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the irregexp code has been generated for the actual string 50233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // encoding. If it has, the field contains a code object otherwise it contains 50243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // a smi (code flushing support). 50253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(t9, &runtime); 5026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: encoding of subject string (1 if ASCII, 0 if two_byte); 5028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t9: code 5029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // subject: Subject string 5030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // regexp_data: RegExp data (FixedArray) 5031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load used arguments before starting to push arguments for call to native 5032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // RegExp code to avoid handling changing stack height. 5033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, kPreviousIndexOffset)); 5034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(a1, a1, kSmiTagSize); // Untag the Smi. 5035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: previous index 5037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: encoding of subject string (1 if ASCII, 0 if two_byte); 5038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t9: code 5039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // subject: Subject string 5040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // regexp_data: RegExp data (FixedArray) 5041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // All checks done. Now push arguments for native regexp code. 50423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(isolate->counters()->regexp_entry_native(), 5043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1, a0, a2); 5044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Isolates: note we add an additional parameter here (isolate pointer). 5046db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kRegExpExecuteArguments = 8; 5047db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kParameterRegisters = 4; 5048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); 5049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stack pointer now points to cell where return address is to be written. 5051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Arguments are before that on the stack or in registers, meaning we 5052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // treat the return address as argument 5. Thus every argument after that 5053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // needs to be shifted back by 1. Since DirectCEntryStub will handle 5054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // allocating space for the c argument slots, we don't need to calculate 5055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // that into the argument positions on the stack. This is how the stack will 5056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // look (sp meaning the value of sp at this moment): 5057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // [sp + 4] - Argument 8 5058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // [sp + 3] - Argument 7 5059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // [sp + 2] - Argument 6 5060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // [sp + 1] - Argument 5 5061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // [sp + 0] - saved ra 5062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument 8: Pass current isolate address. 5064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // CFunctionArgumentOperand handles MIPS stack argument slots. 5065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a0, Operand(ExternalReference::isolate_address())); 5066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a0, MemOperand(sp, 4 * kPointerSize)); 5067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument 7: Indicate that this is a direct call from JavaScript. 5069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a0, Operand(1)); 5070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a0, MemOperand(sp, 3 * kPointerSize)); 5071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument 6: Start (high end) of backtracking stack memory area. 5073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a0, Operand(address_of_regexp_stack_memory_address)); 5074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(a0, 0)); 5075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a2, Operand(address_of_regexp_stack_memory_size)); 5076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, MemOperand(a2, 0)); 5077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(a0, a0, a2); 5078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a0, MemOperand(sp, 2 * kPointerSize)); 5079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument 5: static offsets vector buffer. 5081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a0, Operand( 50823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::address_of_static_offsets_vector(isolate))); 5083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a0, MemOperand(sp, 1 * kPointerSize)); 5084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For arguments 4 and 3 get string length, calculate start of string data 5086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // and calculate the shift of the index (0 for ASCII and 1 for two byte). 50873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(t2, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); 5088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte. 508969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Load the length from the original subject string from the previous stack 509069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // frame. Therefore we have to use fp, which points exactly to two pointer 509169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // sizes below the previous sp. (Because creating a new stack frame pushes 509269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) 5093589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ lw(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); 509469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // If slice offset is not 0, load the length from the original sliced string. 509569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Argument 4, a3: End of string data 509669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Argument 3, a2: Start of string data 509769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Prepare start and end index of the input. 509869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ sllv(t1, t0, a3); 509969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ addu(t0, t2, t1); 5100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(t1, a1, a3); 5101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(a2, t0, t1); 5102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5103589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ lw(t2, FieldMemOperand(subject, String::kLengthOffset)); 510469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ sra(t2, t2, kSmiTagSize); 510569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ sllv(t1, t2, a3); 510669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ addu(a3, t0, t1); 5107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument 2 (a1): Previous index. 5108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Already there 5109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument 1 (a0): Subject string. 5111589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(a0, subject); 5112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Locate the code entry and call it. 5114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); 5115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DirectCEntryStub stub; 5116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch stub.GenerateCall(masm, t9); 5117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LeaveExitFrame(false, no_reg); 5119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v0: result 5121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // subject: subject string (callee saved) 5122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // regexp_data: RegExp data (callee saved) 5123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // last_match_info_elements: Last match info elements (callee saved) 5124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the result. 5126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label success; 51283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&success, eq, v0, Operand(NativeRegExpMacroAssembler::SUCCESS)); 5129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label failure; 51303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE)); 5131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If not exception it can only be retry. Handle that in the runtime system. 51323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); 5133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Result must now be exception. If there is no pending exception already a 5134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // stack overflow (on the backtrack stack) was detected in RegExp code but 5135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // haven't created the exception yet. Handle that in the runtime system. 5136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // TODO(592): Rerunning the RegExp to get the stack overflow exception. 51373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a1, Operand(isolate->factory()->the_hole_value())); 5138589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ li(a2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 51393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate))); 5140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, MemOperand(a2, 0)); 5141589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Branch(&runtime, eq, v0, Operand(a1)); 5142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, MemOperand(a2, 0)); // Clear pending exception. 5144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the exception is a termination. If so, throw as uncatchable. 5146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(a0, Heap::kTerminationExceptionRootIndex); 5147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label termination_exception; 5148589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Branch(&termination_exception, eq, v0, Operand(a0)); 5149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 51503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Throw(v0); 5151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&termination_exception); 51533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ThrowUncatchable(v0); 5154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&failure); 5156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For failure and exception return null. 51573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(v0, Operand(isolate->factory()->null_value())); 51583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(4); 5159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Process the result from the native regexp code. 5161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&success); 5162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, 5163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 5164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate number of capture registers (number_of_captures + 1) * 2. 5165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 5166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 5167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a1, a1, Operand(2)); // a1 was a smi. 5168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: number of capture registers 5170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // subject: subject string 5171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Store the capture count. 5172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(a2, a1, kSmiTagSize + kSmiShiftSize); // To smi. 5173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, FieldMemOperand(last_match_info_elements, 5174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RegExpImpl::kLastCaptureCountOffset)); 5175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Store last subject and last input. 5176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(subject, 5177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(last_match_info_elements, 5178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RegExpImpl::kLastSubjectOffset)); 51793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(a2, subject); 51803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(last_match_info_elements, 51813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RegExpImpl::kLastSubjectOffset, 51823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a2, 51833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch t3, 51843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kRAHasNotBeenSaved, 51853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 5186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(subject, 5187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(last_match_info_elements, 5188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RegExpImpl::kLastInputOffset)); 51893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(last_match_info_elements, 51903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RegExpImpl::kLastInputOffset, 51913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch subject, 51923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch t3, 51933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kRAHasNotBeenSaved, 51943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 5195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the static offsets vector filled by the native regexp code. 5197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference address_of_static_offsets_vector = 51983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::address_of_static_offsets_vector(isolate); 5199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a2, Operand(address_of_static_offsets_vector)); 5200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: number of capture registers 5202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: offsets vector 5203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label next_capture, done; 5204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Capture register counter starts from number of capture registers and 5205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // counts down until wrapping after zero. 5206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a0, 5207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch last_match_info_elements, 5208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag)); 5209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&next_capture); 5210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(a1, a1, Operand(1)); 5211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, lt, a1, Operand(zero_reg)); 5212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Read the value from the static offsets vector buffer. 5213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, MemOperand(a2, 0)); 5214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(a2, a2, kPointerSize); 5215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Store the smi value in the last match info. 5216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(a3, a3, kSmiTagSize); // Convert to Smi. 5217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, MemOperand(a0, 0)); 5218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&next_capture, USE_DELAY_SLOT); 52193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addiu(a0, a0, kPointerSize); // In branch delay slot. 5220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 5222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return last match info. 5224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, MemOperand(sp, kLastMatchInfoOffset)); 52253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(4); 52263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 52273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // External string. Short external strings have already been ruled out. 52283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a0: scratch 52293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&external_string); 52303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); 52313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 52323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 52333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert that we do not have a cons or slice (indirect strings) here. 52343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sequential strings have already been ruled out. 52353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(at, a0, Operand(kIsIndirectStringMask)); 52363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(eq, 52373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch "external string expected, but not found", 52383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch at, 52393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(zero_reg)); 52403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 52413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(subject, 52423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(subject, ExternalString::kResourceDataOffset)); 52433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Move the pointer so that offset-wise, it looks like a sequential string. 52443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); 52453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Subu(subject, 52463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch subject, 52473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SeqTwoByteString::kHeaderSize - kHeapObjectTag); 52483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&seq_string); 5249592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 5250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do the runtime call to execute the regexp. 5251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&runtime); 5252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 5253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif // V8_INTERPRETED_REGEXP 525444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 525544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 525644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 525744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RegExpConstructResultStub::Generate(MacroAssembler* masm) { 5258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kMaxInlineLength = 100; 5259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slowcase; 5260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 5261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, kPointerSize * 2)); 5262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 5263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTagSize == 1); 5264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(a1, &slowcase); 5265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&slowcase, hi, a1, Operand(Smi::FromInt(kMaxInlineLength))); 5266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Smi-tagging is equivalent to multiplying by 2. 5267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate RegExpResult followed by FixedArray with size in ebx. 5268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // JSArray: [Map][empty properties][Elements][Length-smi][index][input] 5269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Elements: [Map][Length][..elements..] 5270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Size of JSArray with two in-object properties and the header of a 5271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // FixedArray. 5272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int objects_size = 5273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize; 5274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(t1, a1, kSmiTagSize + kSmiShiftSize); 5275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a2, t1, Operand(objects_size)); 5276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateInNewSpace( 5277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a2, // In: Size, in words. 5278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch v0, // Out: Start of allocation (tagged). 5279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a3, // Scratch register. 5280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch t0, // Scratch register. 5281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &slowcase, 5282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); 5283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v0: Start of allocated area, object-tagged. 5284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: Number of elements in array, as smi. 5285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t1: Number of elements, untagged. 5286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set JSArray map to global.regexp_result_map(). 5288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set empty properties FixedArray. 5289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set elements to point to FixedArray allocated right after the JSArray. 5290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Interleave operations for better latency. 5291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, ContextOperand(cp, Context::GLOBAL_INDEX)); 5292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a3, v0, Operand(JSRegExpResult::kSize)); 5293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t0, Operand(masm->isolate()->factory()->empty_fixed_array())); 5294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalContextOffset)); 5295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); 5296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, ContextOperand(a2, Context::REGEXP_RESULT_MAP_INDEX)); 5297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset)); 5298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); 5299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set input, index and length fields from arguments. 5301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, kPointerSize * 0)); 53023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a2, MemOperand(sp, kPointerSize * 1)); 53033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t2, MemOperand(sp, kPointerSize * 2)); 5304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, FieldMemOperand(v0, JSRegExpResult::kInputOffset)); 53053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a2, FieldMemOperand(v0, JSRegExpResult::kIndexOffset)); 53063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(t2, FieldMemOperand(v0, JSArray::kLengthOffset)); 5307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fill out the elements FixedArray. 5309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v0: JSArray, tagged. 5310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: FixedArray, tagged. 5311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t1: Number of elements in array, untagged. 5312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set map. 5314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a2, Operand(masm->isolate()->factory()->fixed_array_map())); 5315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, FieldMemOperand(a3, HeapObject::kMapOffset)); 5316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set FixedArray length. 5317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t2, t1, kSmiTagSize); 5318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t2, FieldMemOperand(a3, FixedArray::kLengthOffset)); 5319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fill contents of fixed-array with the-hole. 5320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a2, Operand(masm->isolate()->factory()->the_hole_value())); 5321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 5322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fill fixed array elements with hole. 5323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v0: JSArray, tagged. 5324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: the hole. 5325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: Start of elements in FixedArray. 5326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t1: Number of elements to fill. 5327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label loop; 5328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t1, t1, kPointerSizeLog2); // Convert num elements to num bytes. 5329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t1, t1, a3); // Point past last element to store. 5330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&loop); 5331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, ge, a3, Operand(t1)); // Break when a3 past end of elem. 5332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, MemOperand(a3)); 5333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&loop, USE_DELAY_SLOT); 5334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(a3, a3, kPointerSize); // In branch delay slot. 5335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 53373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(3); 5338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slowcase); 5340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); 534144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 534244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 534344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 53443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateRecordCallTarget(MacroAssembler* masm) { 53453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cache the called function in a global property cell. Cache states 53463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // are uninitialized, monomorphic (indicated by a JSFunction), and 53473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // megamorphic. 53483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1 : the function to call 53493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a2 : cache cell for call target 53503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 53513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 53523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), 53533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->heap()->undefined_value()); 53543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), 53553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->heap()->the_hole_value()); 53563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 53573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the cache state into a3. 53583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset)); 53593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 53603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A monomorphic cache hit or an already megamorphic state: invoke the 53613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // function without changing the state. 53623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&done, eq, a3, Operand(a1)); 53633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 53643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&done, eq, a3, Operand(at)); 53653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 53663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A monomorphic miss (i.e, here the cache is not uninitialized) goes 53673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // megamorphic. 53683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 53693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 53703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(USE_DELAY_SLOT, &done, eq, a3, Operand(at)); 53713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // An uninitialized cache is patched with the function. 53723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store a1 in the delay slot. This may or may not get overwritten depending 53733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // on the result of the comparison. 53743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a1, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset)); 53753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // No need for a write barrier here - cells are rescanned. 53763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 53773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MegamorphicSentinel is an immortal immovable object (undefined) so no 53783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // write-barrier is needed. 53793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 53803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(at, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset)); 53813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 53823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 53833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 53843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 53853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 538644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid CallFunctionStub::Generate(MacroAssembler* masm) { 53873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1 : the function to call 53883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a2 : cache cell for call target 53893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label slow, non_function; 5390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The receiver might implicitly be the global object. This is 5392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // indicated by passing the hole as the receiver to the call 5393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // function stub. 5394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (ReceiverMightBeImplicit()) { 5395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label call; 5396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the receiver from the stack. 5397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // function, receiver [, arguments] 5398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, MemOperand(sp, argc_ * kPointerSize)); 5399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call as function is indicated with the hole. 5400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 5401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&call, ne, t0, Operand(at)); 5402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Patch the receiver on the stack with the global receiver object. 54033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 54043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); 54053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a2, MemOperand(sp, argc_ * kPointerSize)); 5406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call); 5407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the function is really a JavaScript function. 5410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: pushed function (to be verified) 54113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(a1, &non_function); 5412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the map of the function object. 5413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a1, a2, a2); 5414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE)); 5415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fast-case: Invoke the function now. 5417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: pushed function 5418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ParameterCount actual(argc_); 5419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (ReceiverMightBeImplicit()) { 5421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label call_as_function; 5422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 5423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&call_as_function, eq, t0, Operand(at)); 54243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ InvokeFunction(a1, 54253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch actual, 54263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch JUMP_FUNCTION, 54273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch NullCallWrapper(), 54283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CALL_AS_METHOD); 5429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_as_function); 5430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(a1, 5432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch actual, 5433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JUMP_FUNCTION, 5434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), 5435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CALL_AS_FUNCTION); 5436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Slow-case: Non-function called. 5438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 54393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for function proxy. 54403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&non_function, ne, a2, Operand(JS_FUNCTION_PROXY_TYPE)); 54413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(a1); // Put proxy as additional argument. 54423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a0, Operand(argc_ + 1, RelocInfo::NONE)); 54433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a2, Operand(0, RelocInfo::NONE)); 54443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY); 54453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SetCallKind(t1, CALL_AS_METHOD); 54463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 54473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> adaptor = 54483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); 54493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(adaptor, RelocInfo::CODE_TARGET); 54503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 54513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 5453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // of the original receiver from the call site). 54543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&non_function); 5455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, MemOperand(sp, argc_ * kPointerSize)); 54563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a0, Operand(argc_)); // Set up the number of arguments. 5457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(a2, zero_reg); 5458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION); 54593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SetCallKind(t1, CALL_AS_METHOD); 5460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 5461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::CODE_TARGET); 546244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 546344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 546444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 54653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallConstructStub::Generate(MacroAssembler* masm) { 54663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a0 : number of arguments 54673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1 : the function to call 54683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a2 : cache cell for call target 54693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label slow, non_function_call; 54703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 54713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the function is not a smi. 54723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(a1, &non_function_call); 54733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the function is a JSFunction. 54743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ GetObjectType(a1, a3, a3); 54753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE)); 54763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 54773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (RecordCallTarget()) { 54783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateRecordCallTarget(masm); 54793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 54803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 54813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Jump to the function-specific construct stub. 54823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 54833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kConstructStubOffset)); 54843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag)); 54853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(at); 54863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 54873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a0: number of arguments 54883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1: called object 54893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a3: object type 54903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label do_call; 54913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 54923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&non_function_call, ne, a3, Operand(JS_FUNCTION_PROXY_TYPE)); 54933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); 54943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&do_call); 54953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 54963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&non_function_call); 54973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 54983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&do_call); 54993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set expected number of arguments to zero (not changing r0). 55003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a2, Operand(0, RelocInfo::NONE)); 55013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SetCallKind(t1, CALL_AS_METHOD); 55023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 55033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::CODE_TARGET); 55043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 55053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 55063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 550744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Unfortunately you have to run without snapshots to see most of these 550844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// names in the profile since most compare stubs end up in the snapshot. 55093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid CompareStub::PrintName(StringStream* stream) { 5510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT((lhs_.is(a0) && rhs_.is(a1)) || 5511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (lhs_.is(a1) && rhs_.is(a0))); 5512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const char* cc_name; 5513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (cc_) { 5514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case lt: cc_name = "LT"; break; 5515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case gt: cc_name = "GT"; break; 5516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case le: cc_name = "LE"; break; 5517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case ge: cc_name = "GE"; break; 5518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case eq: cc_name = "EQ"; break; 5519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case ne: cc_name = "NE"; break; 5520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: cc_name = "UnknownCondition"; break; 5521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 55223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_equality = cc_ == eq || cc_ == ne; 55233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch stream->Add("CompareStub_%s", cc_name); 55243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch stream->Add(lhs_.is(a0) ? "_a0" : "_a1"); 55253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch stream->Add(rhs_.is(a0) ? "_a0" : "_a1"); 55263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (strict_ && is_equality) stream->Add("_STRICT"); 55273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (never_nan_nan_ && is_equality) stream->Add("_NO_NAN"); 55283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!include_number_compare_) stream->Add("_NO_NUMBER"); 55293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!include_smi_compare_) stream->Add("_NO_SMI"); 553044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 553144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 553244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 553344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint CompareStub::MinorKey() { 5534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Encode the two parameters in a unique 16 bit value. 5535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(static_cast<unsigned>(cc_) < (1 << 14)); 5536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT((lhs_.is(a0) && rhs_.is(a1)) || 5537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (lhs_.is(a1) && rhs_.is(a0))); 5538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ConditionField::encode(static_cast<unsigned>(cc_)) 5539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch | RegisterField::encode(lhs_.is(a0)) 5540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch | StrictField::encode(strict_) 5541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false) 5542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch | IncludeSmiCompareField::encode(include_smi_compare_); 554344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 554444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 554544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// StringCharCodeAtGenerator. 554744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 5548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label flat_string; 5549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ascii_string; 5550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label got_char_code; 555169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label sliced_string; 5552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!t0.is(index_)); 5554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!t0.is(result_)); 5555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!t0.is(object_)); 5556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the receiver is a smi trigger the non-string case. 5558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(object_, receiver_not_string_); 5559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fetch the instance type of the receiver into result register. 5561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 5562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 5563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the receiver is not a string trigger the non-string case. 5564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t0, result_, Operand(kIsNotStringMask)); 5565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(receiver_not_string_, ne, t0, Operand(zero_reg)); 5566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the index is non-smi trigger the non-smi case. 5568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(index_, &index_not_smi_); 5569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&got_smi_index_); 5571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for index out of range. 5573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, FieldMemOperand(object_, String::kLengthOffset)); 55743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(index_out_of_range_, ls, t0, Operand(index_)); 557585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 55763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sra(index_, index_, kSmiTagSize); 557785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 55783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharLoadGenerator::Generate(masm, 55793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object_, 55803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_, 55813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result_, 55823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_runtime_); 558385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 5584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(result_, result_, kSmiTagSize); 5585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&exit_); 558644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 558744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 558844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 558944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringCharCodeAtGenerator::GenerateSlow( 55903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 55913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const RuntimeCallHelper& call_helper) { 5592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Abort("Unexpected fallthrough to CharCodeAt slow case"); 5593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Index is not a smi. 5595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&index_not_smi_); 5596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If index is a heap number, try converting it to an integer. 5597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(index_, 55983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result_, 5599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap::kHeapNumberMapRootIndex, 5600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch index_not_number_, 5601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DONT_DO_SMI_CHECK); 5602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_helper.BeforeCall(masm); 5603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Consumed by runtime conversion function: 56043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(object_, index_); 5605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (index_flags_ == STRING_INDEX_IS_NUMBER) { 5606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); 5607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 5608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 5609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // NumberToSmi discards numbers that are not exact integers. 5610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CallRuntime(Runtime::kNumberToSmi, 1); 5611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Save the conversion result before the pop instructions below 5614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have a chance to overwrite it. 5615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 56163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(index_, v0); 5617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ pop(object_); 5618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Reload the instance type. 5619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 5620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 5621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_helper.AfterCall(masm); 5622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If index is still not a smi, it must be out of range. 56233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(index_, index_out_of_range_); 5624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Otherwise, return to the fast path. 5625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&got_smi_index_); 5626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call runtime. We get here when the receiver is a string and the 5628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // index is a number, but the code of getting the actual character 5629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // is too complex (e.g., when the string needs to be flattened). 5630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_runtime_); 5631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_helper.BeforeCall(masm); 56323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(index_, index_, kSmiTagSize); 5633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(object_, index_); 5634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CallRuntime(Runtime::kStringCharCodeAt, 2); 5635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(result_, v0); 5637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_helper.AfterCall(masm); 5639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&exit_); 5640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Abort("Unexpected fallthrough from CharCodeAt slow case"); 564244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 564344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 564444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 564544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// ------------------------------------------------------------------------- 564644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// StringCharFromCodeGenerator 564744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 564844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 5649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fast case of Heap::LookupSingleCharacterStringFromCode. 5650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!t0.is(result_)); 5652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!t0.is(code_)); 5653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 5655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiShiftSize == 0); 5656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); 5657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t0, 5658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch code_, 5659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(kSmiTagMask | 5660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ((~String::kMaxAsciiCharCode) << kSmiTagSize))); 5661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&slow_case_, ne, t0, Operand(zero_reg)); 5662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); 5664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // At this point code register contains smi tagged ASCII char code. 5665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 5666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t0, code_, kPointerSizeLog2 - kSmiTagSize); 5667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(result_, result_, t0); 5668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); 5669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); 5670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&slow_case_, eq, result_, Operand(t0)); 5671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&exit_); 567244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 567344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 567444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 567544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringCharFromCodeGenerator::GenerateSlow( 56763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 56773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const RuntimeCallHelper& call_helper) { 5678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Abort("Unexpected fallthrough to CharFromCode slow case"); 5679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow_case_); 5681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_helper.BeforeCall(masm); 5682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(code_); 5683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CallRuntime(Runtime::kCharFromCode, 1); 5684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(result_, v0); 5685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call_helper.AfterCall(masm); 5687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&exit_); 5688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Abort("Unexpected fallthrough from CharFromCode slow case"); 569044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 569144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 569244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 569344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// ------------------------------------------------------------------------- 569444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// StringCharAtGenerator 569544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 569644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringCharAtGenerator::GenerateFast(MacroAssembler* masm) { 5697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char_code_at_generator_.GenerateFast(masm); 5698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char_from_code_generator_.GenerateFast(masm); 569944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 570044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 570144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 570244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringCharAtGenerator::GenerateSlow( 57033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 57043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const RuntimeCallHelper& call_helper) { 5705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char_code_at_generator_.GenerateSlow(masm, call_helper); 5706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char_from_code_generator_.GenerateSlow(masm, call_helper); 570744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 570844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 570944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 571044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringHelper::GenerateCopyCharacters(MacroAssembler* masm, 571144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register dest, 571244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register src, 571344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register count, 571444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 571544f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool ascii) { 5716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label loop; 5717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 5718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This loop just copies one character at a time, as it is only used for 5719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // very short strings. 5720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!ascii) { 5721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(count, count, count); 5722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, eq, count, Operand(zero_reg)); 5724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(count, dest, count); // Count now points to the last dest byte. 5725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&loop); 5727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(scratch, MemOperand(src)); 5728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(src, src, 1); 5729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sb(scratch, MemOperand(dest)); 5730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(dest, dest, 1); 5731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&loop, lt, dest, Operand(count)); 5732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 573444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 573544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 573644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 573744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockenum CopyCharactersFlags { 573844f0eee88ff00398ff7f715fab053374d808c90dSteve Block COPY_ASCII = 1, 573944f0eee88ff00398ff7f715fab053374d808c90dSteve Block DEST_ALWAYS_ALIGNED = 2 574044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 574144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 574244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 574344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm, 574444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register dest, 574544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register src, 574644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register count, 574744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 574844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 574944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch3, 575044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch4, 575144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch5, 575244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int flags) { 5753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool ascii = (flags & COPY_ASCII) != 0; 5754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0; 5755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (dest_always_aligned && FLAG_debug_code) { 5757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that destination is actually word aligned if the flag says 5758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // that it is. 5759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch4, dest, Operand(kPointerAlignmentMask)); 5760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Check(eq, 5761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "Destination of copy not aligned.", 5762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch4, 5763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(zero_reg)); 5764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kReadAlignment = 4; 5767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kReadAlignmentMask = kReadAlignment - 1; 5768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Ensure that reading an entire aligned word containing the last character 5769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // of a string will not read outside the allocated area (because we pad up 5770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // to kObjectAlignment). 5771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kObjectAlignment >= kReadAlignment); 5772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Assumes word reads and writes are little endian. 5773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Nothing to do for zero characters. 5774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 5775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!ascii) { 5777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(count, count, count); 5778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, eq, count, Operand(zero_reg)); 5780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label byte_loop; 5782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Must copy at least eight bytes, otherwise just do it one byte at a time. 5783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(scratch1, count, Operand(8)); 5784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(count, dest, Operand(count)); 5785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register limit = count; // Read until src equals this. 5786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&byte_loop, lt, scratch1, Operand(zero_reg)); 5787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!dest_always_aligned) { 5789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Align dest by byte copying. Copies between zero and three bytes. 5790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch4, dest, Operand(kReadAlignmentMask)); 5791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label dest_aligned; 5792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&dest_aligned, eq, scratch4, Operand(zero_reg)); 5793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label aligned_loop; 5794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&aligned_loop); 5795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(scratch1, MemOperand(src)); 5796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(src, src, 1); 5797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sb(scratch1, MemOperand(dest)); 5798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(dest, dest, 1); 5799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(scratch4, scratch4, 1); 5800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&aligned_loop, le, scratch4, Operand(kReadAlignmentMask)); 5801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&dest_aligned); 5802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label simple_loop; 5805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch4, src, Operand(kReadAlignmentMask)); 5807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&simple_loop, eq, scratch4, Operand(zero_reg)); 5808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Loop for src/dst that are not aligned the same way. 5810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This loop uses lwl and lwr instructions. These instructions 5811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // depend on the endianness, and the implementation assumes little-endian. 5812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch { 5813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label loop; 5814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&loop); 5815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lwr(scratch1, MemOperand(src)); 5816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(src, src, Operand(kReadAlignment)); 5817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lwl(scratch1, MemOperand(src, -1)); 5818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(scratch1, MemOperand(dest)); 5819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(dest, dest, Operand(kReadAlignment)); 5820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(scratch2, limit, dest); 5821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&loop, ge, scratch2, Operand(kReadAlignment)); 5822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&byte_loop); 5825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Simple loop. 5827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Copy words from src to dest, until less than four bytes left. 5828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Both src and dest are word aligned. 5829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&simple_loop); 5830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch { 5831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label loop; 5832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&loop); 5833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, MemOperand(src)); 5834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(src, src, Operand(kReadAlignment)); 5835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(scratch1, MemOperand(dest)); 5836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(dest, dest, Operand(kReadAlignment)); 5837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(scratch2, limit, dest); 5838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&loop, ge, scratch2, Operand(kReadAlignment)); 5839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Copy bytes from src to dest until dest hits limit. 5842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&byte_loop); 5843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Test if dest has already reached the limit. 5844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, ge, dest, Operand(limit)); 5845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(scratch1, MemOperand(src)); 5846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(src, src, 1); 5847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sb(scratch1, MemOperand(dest)); 5848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addiu(dest, dest, 1); 5849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&byte_loop); 5850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 585244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 585344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 585444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 585544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, 585644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register c1, 585744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register c2, 585844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 585944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 586044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch3, 586144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch4, 586244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch5, 586344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* not_found) { 5864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Register scratch3 is the general scratch register in this function. 5865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch = scratch3; 5866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure that both characters are not digits as such strings has a 5868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // different hash algorithm. Don't try to look for these in the symbol table. 5869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_array_index; 5870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(scratch, c1, Operand(static_cast<int>('0'))); 5871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_array_index, 5872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Ugreater, 5873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch, 5874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(static_cast<int>('9' - '0'))); 5875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(scratch, c2, Operand(static_cast<int>('0'))); 5876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If check failed combine both characters into single halfword. 5878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This is required by the contract of the method: code at the 5879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // not_found branch expects this combination in c1 register. 5880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label tmp; 5881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(scratch1, c2, kBitsPerByte); 5882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&tmp, Ugreater, scratch, Operand(static_cast<int>('9' - '0'))); 5883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(c1, c1, scratch1); 5884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&tmp); 58853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch( 58863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch not_found, Uless_equal, scratch, Operand(static_cast<int>('9' - '0'))); 5887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_array_index); 5889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate the two character string hash. 5890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register hash = scratch1; 5891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringHelper::GenerateHashInit(masm, hash, c1); 5892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringHelper::GenerateHashAddCharacter(masm, hash, c2); 5893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringHelper::GenerateHashGetHash(masm, hash); 5894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Collect the two characters in a register. 5896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register chars = c1; 5897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(scratch, c2, kBitsPerByte); 5898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(chars, chars, scratch); 5899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // chars: two character string, char 1 in byte 0 and char 2 in byte 1. 5901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // hash: hash of two character string. 5902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load symbol table. 5904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load address of first element of the symbol table. 5905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register symbol_table = c2; 5906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex); 5907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register undefined = scratch4; 5909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); 5910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate capacity mask from the symbol table capacity. 5912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register mask = scratch2; 5913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(mask, FieldMemOperand(symbol_table, SymbolTable::kCapacityOffset)); 5914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(mask, mask, 1); 5915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(mask, mask, -1); 5916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate untagged address of the first element of the symbol table. 5918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register first_symbol_table_element = symbol_table; 5919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(first_symbol_table_element, symbol_table, 5920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(SymbolTable::kElementsStartOffset - kHeapObjectTag)); 5921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers. 5923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // chars: two character string, char 1 in byte 0 and char 2 in byte 1. 5924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // hash: hash of two character string 5925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // mask: capacity mask 5926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // first_symbol_table_element: address of the first element of 5927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the symbol table 5928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // undefined: the undefined object 5929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // scratch: - 5930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Perform a number of probes in the symbol table. 5932db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kProbes = 4; 5933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label found_in_symbol_table; 5934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label next_probe[kProbes]; 5935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register candidate = scratch5; // Scratch register contains candidate. 5936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < kProbes; i++) { 5937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate entry in symbol table. 5938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i > 0) { 5939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(candidate, hash, Operand(SymbolTable::GetProbeOffset(i))); 5940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 5941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(candidate, hash); 5942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(candidate, candidate, Operand(mask)); 5945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the entry from the symble table. 5947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(SymbolTable::kEntrySize == 1); 5948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(scratch, candidate, kPointerSizeLog2); 5949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch, scratch, first_symbol_table_element); 5950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(candidate, MemOperand(scratch)); 5951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If entry is undefined no string with this hash can be found. 5953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label is_string; 5954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(candidate, scratch, scratch); 5955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&is_string, ne, scratch, Operand(ODDBALL_TYPE)); 5956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(not_found, eq, undefined, Operand(candidate)); 59583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Must be the hole (deleted entry). 5959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (FLAG_debug_code) { 59603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); 59613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(eq, "oddball in symbol table is not undefined or the hole", 5962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch, Operand(candidate)); 5963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&next_probe[i]); 5965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&is_string); 5967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the candidate is a non-external ASCII string. The instance 5969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // type is still in the scratch register from the CompareObjectType 5970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // operation. 5971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); 5972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If length is not 2 the string is not a candidate. 5974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch, FieldMemOperand(candidate, String::kLengthOffset)); 5975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&next_probe[i], ne, scratch, Operand(Smi::FromInt(2))); 5976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the two characters match. 5978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Assumes that word load is little endian. 5979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lhu(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize)); 5980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&found_in_symbol_table, eq, chars, Operand(scratch)); 5981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&next_probe[i]); 5982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // No matching 2 character string found by probing. 5985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(not_found); 5986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Scratch register contains result when we fall through to here. 5988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result = candidate; 5989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&found_in_symbol_table); 5990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, result); 599144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 599244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 599344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 599444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringHelper::GenerateHashInit(MacroAssembler* masm, 5995c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Register hash, 5996c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Register character) { 5997c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // hash = seed + character + ((seed + character) << 10); 5998c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ LoadRoot(hash, Heap::kHashSeedRootIndex); 5999c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Untag smi seed and add the character. 6000c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ SmiUntag(hash); 6001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(hash, hash, character); 6002c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ sll(at, hash, 10); 6003c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ addu(hash, hash, at); 6004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // hash ^= hash >> 6; 60053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ srl(at, hash, 6); 6006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xor_(hash, hash, at); 600744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 600844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 600944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 601044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringHelper::GenerateHashAddCharacter(MacroAssembler* masm, 6011c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Register hash, 6012c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Register character) { 6013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // hash += character; 6014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(hash, hash, character); 6015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // hash += hash << 10; 6016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(at, hash, 10); 6017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(hash, hash, at); 6018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // hash ^= hash >> 6; 60193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ srl(at, hash, 6); 6020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xor_(hash, hash, at); 602144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 602244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 602344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 602444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringHelper::GenerateHashGetHash(MacroAssembler* masm, 6025c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Register hash) { 6026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // hash += hash << 3; 6027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(at, hash, 3); 6028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(hash, hash, at); 6029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // hash ^= hash >> 11; 60303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ srl(at, hash, 11); 6031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xor_(hash, hash, at); 6032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // hash += hash << 15; 6033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(at, hash, 15); 6034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(hash, hash, at); 6035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 60363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(at, Operand(String::kHashBitMask)); 60373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ and_(hash, hash, at); 60383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // if (hash == 0) hash = 27; 60403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ori(at, zero_reg, StringHasher::kZeroHash); 60413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(hash, at, hash); 604244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 604344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 604444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 604544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid SubStringStub::Generate(MacroAssembler* masm) { 60463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label runtime; 6047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stack frame on entry. 6048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ra: return address 6049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[0]: to 6050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[4]: from 6051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[8]: string 6052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is called from the native-call %_SubString(...), so 6054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // nothing can be assumed about the arguments. It is tested that: 6055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // "string" is a sequential string, 6056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // both "from" and "to" are smis, and 6057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 0 <= from <= to <= string.length. 6058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If any of these assumptions fail, we call the runtime system. 6059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6060db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kToOffset = 0 * kPointerSize; 6061db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kFromOffset = 1 * kPointerSize; 6062db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kStringOffset = 2 * kPointerSize; 6063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 60643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a2, MemOperand(sp, kToOffset)); 60653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, MemOperand(sp, kFromOffset)); 6066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kFromOffset == kToOffset + 4); 6067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 6068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 6069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 60703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Utilize delay slots. SmiUntag doesn't emit a jump, everything else is 60713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // safe in this case. 60723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ UntagAndJumpIfNotSmi(a2, a2, &runtime); 60733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ UntagAndJumpIfNotSmi(a3, a3, &runtime); 60743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Both a2 and a3 are untagged integers. 607585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 60763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&runtime, lt, a3, Operand(zero_reg)); // From < 0. 607785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 60783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&runtime, gt, a3, Operand(a2)); // Fail if from > to. 60793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Subu(a2, a2, a3); 6080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 60813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure first argument is a string. 6082589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ lw(v0, MemOperand(sp, kStringOffset)); 60833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(v0, &runtime); 6084589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); 6085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset)); 60863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t0, a1, Operand(kIsNotStringMask)); 6087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 60883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&runtime, ne, t0, Operand(zero_reg)); 6089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6090589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Short-cut for the case of trivial substring. 6091589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label return_v0; 6092589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // v0: original string 6093589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // a2: result string length 6094589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ lw(t0, FieldMemOperand(v0, String::kLengthOffset)); 6095589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ sra(t0, t0, 1); 6096589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Branch(&return_v0, eq, a2, Operand(t0)); 6097589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 609885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 609985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch Label result_longer_than_two; 61003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for special case of two character ASCII string, in which case 61013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // we do a lookup in the symbol table first. 61023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(t0, 2); 61033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&result_longer_than_two, gt, a2, Operand(t0)); 61043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&runtime, lt, a2, Operand(t0)); 61053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 61063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfInstanceTypeIsNotSequentialAscii(a1, a1, &runtime); 610785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 6108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the two characters forming the sub string. 6109589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Addu(v0, v0, Operand(a3)); 6110589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ lbu(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize)); 6111589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ lbu(t0, FieldMemOperand(v0, SeqAsciiString::kHeaderSize + 1)); 6112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Try to lookup two character string in symbol table. 6114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label make_two_character_string; 6115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringHelper::GenerateTwoCharacterSymbolTableProbe( 6116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm, a3, t0, a1, t1, t2, t3, t4, &make_two_character_string); 6117589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ jmp(&return_v0); 6118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: result string length. 6120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: two characters combined into halfword in little endian byte order. 6121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&make_two_character_string); 61223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateAsciiString(v0, a2, t0, t1, t4, &runtime); 6123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sh(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize)); 6124589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ jmp(&return_v0); 6125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&result_longer_than_two); 6127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 61283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Deal with different string types: update the index if necessary 61293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and put the underlying string into t1. 61303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // v0: original string 61313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1: instance type 61323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a2: length 61333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a3: from index (untagged) 61343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label underlying_unpacked, sliced_string, seq_or_external_string; 61353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the string is not indirect, it can only be sequential or external. 61363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); 61373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kIsIndirectStringMask != 0); 61383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t0, a1, Operand(kIsIndirectStringMask)); 61393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(USE_DELAY_SLOT, &seq_or_external_string, eq, t0, Operand(zero_reg)); 61403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // t0 is used as a scratch register and can be overwritten in either case. 61413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t0, a1, Operand(kSlicedNotConsMask)); 61423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&sliced_string, ne, t0, Operand(zero_reg)); 61433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cons string. Check whether it is flat, then fetch first part. 61443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t1, FieldMemOperand(v0, ConsString::kSecondOffset)); 61453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(t0, Heap::kEmptyStringRootIndex); 61463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&runtime, ne, t1, Operand(t0)); 61473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t1, FieldMemOperand(v0, ConsString::kFirstOffset)); 61483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update instance type. 61493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a1, FieldMemOperand(t1, HeapObject::kMapOffset)); 61503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset)); 61513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&underlying_unpacked); 61523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 61533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&sliced_string); 61543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sliced string. Fetch parent and correct start index by offset. 61553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t1, FieldMemOperand(v0, SlicedString::kParentOffset)); 61563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t0, FieldMemOperand(v0, SlicedString::kOffsetOffset)); 61573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sra(t0, t0, 1); // Add offset to index. 61583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(a3, a3, t0); 61593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update instance type. 61603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a1, FieldMemOperand(t1, HeapObject::kMapOffset)); 61613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset)); 61623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&underlying_unpacked); 6163c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 61643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&seq_or_external_string); 61653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sequential or external string. Just move string to the expected register. 61663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(t1, v0); 61673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 61683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&underlying_unpacked); 61693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 61703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_string_slices) { 61713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label copy_routine; 61723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // t1: underlying subject string 61733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1: instance type of underlying subject string 61743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a2: length 61753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a3: adjusted start index (untagged) 61763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Short slice. Copy instead of slicing. 61773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(©_routine, lt, a2, Operand(SlicedString::kMinLength)); 61783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate new sliced string. At this point we do not reload the instance 61793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // type including the string encoding because we simply rely on the info 61803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // provided by the original string. It does not matter if the original 61813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // string's encoding is wrong because we always have to recheck encoding of 61823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the newly created string's parent anyways due to externalized strings. 61833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label two_byte_slice, set_slice_header; 61843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); 61853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 61863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t0, a1, Operand(kStringEncodingMask)); 61873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&two_byte_slice, eq, t0, Operand(zero_reg)); 61883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateAsciiSlicedString(v0, a2, t2, t3, &runtime); 61893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&set_slice_header); 61903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&two_byte_slice); 61913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateTwoByteSlicedString(v0, a2, t2, t3, &runtime); 61923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&set_slice_header); 61933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(a3, a3, 1); 61943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(t1, FieldMemOperand(v0, SlicedString::kParentOffset)); 61953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a3, FieldMemOperand(v0, SlicedString::kOffsetOffset)); 61963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&return_v0); 61973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 61983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(©_routine); 61993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 62003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 62013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // t1: underlying subject string 62023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1: instance type of underlying subject string 62033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a2: length 62043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a3: adjusted start index (untagged) 62053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label two_byte_sequential, sequential_string, allocate_result; 62063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kExternalStringTag != 0); 62073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSeqStringTag == 0); 62083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t0, a1, Operand(kExternalStringTag)); 62093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&sequential_string, eq, t0, Operand(zero_reg)); 62103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 62113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle external string. 62123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Rule out short external strings. 62133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_CHECK(kShortExternalStringTag != 0); 62143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t0, a1, Operand(kShortExternalStringTag)); 62153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&runtime, ne, t0, Operand(zero_reg)); 62163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t1, FieldMemOperand(t1, ExternalString::kResourceDataOffset)); 62173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // t1 already points to the first character of underlying string. 62183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&allocate_result); 62193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 62203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&sequential_string); 62213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Locate first character of underlying subject string. 62223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); 62233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(t1, t1, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 62243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 62253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&allocate_result); 62263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sequential acii string. Allocate the result. 62273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT((kAsciiStringTag & kStringEncodingMask) != 0); 62283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t0, a1, Operand(kStringEncodingMask)); 62293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&two_byte_sequential, eq, t0, Operand(zero_reg)); 62303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 62313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate and copy the resulting ASCII string. 62323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateAsciiString(v0, a2, t0, t2, t3, &runtime); 62333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 62343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Locate first character of substring to copy. 62353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(t1, t1, a3); 6236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Locate first character of result. 6238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a1, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 6239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // v0: result string 6241589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // a1: first character of result string 6242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // a2: result string length 6243589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // t1: first character of substring to copy 6244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); 6245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringHelper::GenerateCopyCharactersLong( 6246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm, a1, t1, a2, a3, t0, t2, t3, t4, COPY_ASCII | DEST_ALWAYS_ALIGNED); 6247589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ jmp(&return_v0); 6248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 62493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate and copy the resulting two-byte string. 62503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&two_byte_sequential); 62513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateTwoByteString(v0, a2, t0, t2, t3, &runtime); 625285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 62533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Locate first character of substring to copy. 62543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 62553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(t0, a3, 1); 62563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(t1, t1, t0); 6257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Locate first character of result. 6258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 6259589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 6260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v0: result string. 6261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: first character of result. 6262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: result length. 6263589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // t1: first character of substring to copy. 6264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 6265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringHelper::GenerateCopyCharactersLong( 6266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm, a1, t1, a2, a3, t0, t2, t3, t4, DEST_ALWAYS_ALIGNED); 6267589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 6268589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&return_v0); 62693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Counters* counters = masm->isolate()->counters(); 6270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); 62713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(3); 6272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Just jump to runtime to create the sub string. 62743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&runtime); 6275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallRuntime(Runtime::kSubString, 3, 1); 6276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, 6280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left, 6281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right, 6282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 6283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2, 6284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch3) { 6285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register length = scratch1; 6286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare lengths. 6288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label strings_not_equal, check_zero_length; 6289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(length, FieldMemOperand(left, String::kLengthOffset)); 6290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch2, FieldMemOperand(right, String::kLengthOffset)); 6291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&check_zero_length, eq, length, Operand(scratch2)); 6292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&strings_not_equal); 6293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(Smi::FromInt(NOT_EQUAL))); 6294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 6295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the length is zero. 6297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label compare_chars; 6298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&check_zero_length); 6299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 6300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&compare_chars, ne, length, Operand(zero_reg)); 6301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(Smi::FromInt(EQUAL))); 6302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 6303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare characters. 6305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&compare_chars); 6306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateAsciiCharsCompareLoop(masm, 6308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch left, right, length, scratch2, scratch3, v0, 6309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &strings_not_equal); 6310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Characters are equal. 6312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(Smi::FromInt(EQUAL))); 6313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 631444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 631544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 631644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 631744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 631844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register left, 6319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right, 632044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 632144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 632244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch3, 632344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch4) { 6324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label result_not_equal, compare_lengths; 6325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Find minimum length and length difference. 6326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, FieldMemOperand(left, String::kLengthOffset)); 6327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch2, FieldMemOperand(right, String::kLengthOffset)); 6328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(scratch3, scratch1, Operand(scratch2)); 6329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register length_delta = scratch3; 6330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ slt(scratch4, scratch2, scratch1); 63313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movn(scratch1, scratch2, scratch4); 6332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register min_length = scratch1; 6333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 6334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&compare_lengths, eq, min_length, Operand(zero_reg)); 6335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare loop. 6337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateAsciiCharsCompareLoop(masm, 6338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch left, right, min_length, scratch2, scratch4, v0, 6339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &result_not_equal); 6340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare lengths - strings up to min-length are equal. 6342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&compare_lengths); 6343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); 6344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use length_delta as result if it's zero. 6345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(scratch2, length_delta); 6346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(scratch4, zero_reg); 6347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, zero_reg); 6348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&result_not_equal); 6350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Conditionally update the result based either on length_delta or 6351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the last comparion performed in the loop above. 6352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ret; 6353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&ret, eq, scratch2, Operand(scratch4)); 6354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(Smi::FromInt(GREATER))); 6355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&ret, gt, scratch2, Operand(scratch4)); 6356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(Smi::FromInt(LESS))); 6357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&ret); 6358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 6359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid StringCompareStub::GenerateAsciiCharsCompareLoop( 6363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 6364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left, 6365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right, 6366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register length, 6367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 6368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2, 6369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch3, 6370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* chars_not_equal) { 6371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Change index to run from -length to -1 by adding length to string 6372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // start. This means that loop ends when index reaches zero, which 6373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // doesn't need an additional compare. 6374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(length); 6375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch1, length, 6376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 6377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(left, left, Operand(scratch1)); 6378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(right, right, Operand(scratch1)); 6379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(length, zero_reg, length); 6380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register index = length; // index = -length; 6381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare loop. 6384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label loop; 6385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&loop); 6386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch3, left, index); 6387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(scratch1, MemOperand(scratch3)); 6388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch3, right, index); 6389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(scratch2, MemOperand(scratch3)); 6390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(chars_not_equal, ne, scratch1, Operand(scratch2)); 6391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(index, index, 1); 6392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&loop, ne, index, Operand(zero_reg)); 639344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 639444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 639544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 639644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringCompareStub::Generate(MacroAssembler* masm) { 6397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label runtime; 6398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 6400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stack frame on entry. 6402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[0]: right string 6403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[4]: left string 6404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, 1 * kPointerSize)); // Left. 6405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(sp, 0 * kPointerSize)); // Right. 6406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_same; 6408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_same, ne, a0, Operand(a1)); 6409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(EQUAL == 0); 6410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 6411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(Smi::FromInt(EQUAL))); 6412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->string_compare_native(), 1, a1, a2); 64133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(2); 6414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_same); 6416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both objects are sequential ASCII strings. 6418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotBothSequentialAsciiStrings(a1, a0, a2, a3, &runtime); 6419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare flat ASCII strings natively. Remove arguments from stack first. 6421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->string_compare_native(), 1, a2, a3); 6422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(sp, sp, Operand(2 * kPointerSize)); 6423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateCompareFlatAsciiStrings(masm, a1, a0, a2, a3, t0, t1); 6424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&runtime); 6426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 642744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 642844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 642944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 643044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StringAddStub::Generate(MacroAssembler* masm) { 64313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label call_runtime, call_builtin; 6432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Builtins::JavaScript builtin_id = Builtins::ADD; 6433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 6435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stack on entry: 6437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[0]: second argument (right). 6438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp[4]: first argument (left). 6439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the two arguments. 6441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(sp, 1 * kPointerSize)); // First argument. 6442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, 0 * kPointerSize)); // Second argument. 6443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure that both arguments are strings if not known in advance. 6445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (flags_ == NO_STRING_ADD_FLAGS) { 64463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfEitherSmi(a0, a1, &call_runtime); 6447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load instance types. 6448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, FieldMemOperand(a0, HeapObject::kMapOffset)); 6449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset)); 6450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset)); 6451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(t1, FieldMemOperand(t1, Map::kInstanceTypeOffset)); 6452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kStringTag == 0); 6453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If either is not a string, go to runtime. 6454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(t4, t0, Operand(t1)); 6455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t4, t4, Operand(kIsNotStringMask)); 64563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&call_runtime, ne, t4, Operand(zero_reg)); 6457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Here at least one of the arguments is definitely a string. 6459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We convert the one that is not known to be a string. 6460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { 6461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); 6462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateConvertArgument( 6463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm, 1 * kPointerSize, a0, a2, a3, t0, t1, &call_builtin); 6464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch builtin_id = Builtins::STRING_ADD_RIGHT; 6465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) { 6466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0); 6467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateConvertArgument( 6468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm, 0 * kPointerSize, a1, a2, a3, t0, t1, &call_builtin); 6469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch builtin_id = Builtins::STRING_ADD_LEFT; 6470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Both arguments are strings. 6474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: first string 6475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: second string 6476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t0: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) 6477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t1: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) 6478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch { 6479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label strings_not_empty; 6480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if either of the strings are empty. In that case return the other. 6481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // These tests use zero-length check on string-length whch is an Smi. 6482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Assert that Smi::FromInt(0) is really 0. 6483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 6484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(Smi::FromInt(0) == 0); 6485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(a0, String::kLengthOffset)); 6486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a1, String::kLengthOffset)); 6487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, a0); // Assume we'll return first string (from a0). 64883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(v0, a1, a2); // If first is empty, return second (from a1). 6489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ slt(t4, zero_reg, a2); // if (a2 > 0) t4 = 1. 6490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ slt(t5, zero_reg, a3); // if (a3 > 0) t5 = 1. 6491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ and_(t4, t4, t5); // Branch if both strings were non-empty. 6492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&strings_not_empty, ne, t4, Operand(zero_reg)); 6493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->string_add_native(), 1, a2, a3); 64953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(2); 6496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&strings_not_empty); 6498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Untag both string-lengths. 6501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(a2, a2, kSmiTagSize); 6502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(a3, a3, kSmiTagSize); 6503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Both strings are non-empty. 6505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: first string 6506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: second string 6507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: length of first string 6508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: length of second string 6509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t0: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) 6510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t1: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) 6511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Look at the length of the result of adding the two strings. 6512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label string_add_flat_result, longer_than_two; 6513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Adding two lengths can't overflow. 6514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); 6515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t2, a2, Operand(a3)); 6516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use the symbol table when adding two one character strings, as it 6517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // helps later optimizations to return a symbol here. 6518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&longer_than_two, ne, t2, Operand(2)); 6519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both strings are non-external ASCII strings. 6521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (flags_ != NO_STRING_ADD_FLAGS) { 6522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, FieldMemOperand(a0, HeapObject::kMapOffset)); 6523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset)); 6524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset)); 6525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(t1, FieldMemOperand(t1, Map::kInstanceTypeOffset)); 6526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfBothInstanceTypesAreNotSequentialAscii(t0, t1, t2, t3, 65283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_runtime); 6529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the two characters forming the sub string. 6531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(a2, FieldMemOperand(a0, SeqAsciiString::kHeaderSize)); 6532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(a3, FieldMemOperand(a1, SeqAsciiString::kHeaderSize)); 6533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Try to lookup two character string in symbol table. If it is not found 6535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // just allocate a new one. 6536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label make_two_character_string; 6537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringHelper::GenerateTwoCharacterSymbolTableProbe( 65383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, a2, a3, t2, t3, t0, t1, t5, &make_two_character_string); 6539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->string_add_native(), 1, a2, a3); 65403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(2); 6541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&make_two_character_string); 6543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Resulting string has length 2 and first chars of two strings 6544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // are combined into single halfword in a2 register. 6545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // So we can fill resulting string without two loops by a single 6546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // halfword store instruction (which assumes that processor is 6547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // in a little endian mode). 6548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t2, Operand(2)); 65493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateAsciiString(v0, t2, t0, t1, t5, &call_runtime); 6550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sh(a2, FieldMemOperand(v0, SeqAsciiString::kHeaderSize)); 6551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->string_add_native(), 1, a2, a3); 65523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(2); 6553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&longer_than_two); 6555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if resulting string will be flat. 65563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&string_add_flat_result, lt, t2, Operand(ConsString::kMinLength)); 6557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle exceptionally long strings in the runtime system. 6558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); 6559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(IsPowerOf2(String::kMaxLength + 1)); 6560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. 65613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&call_runtime, hs, t2, Operand(String::kMaxLength + 1)); 6562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If result is not supposed to be flat, allocate a cons string object. 6564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If both strings are ASCII the result is an ASCII cons string. 6565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (flags_ != NO_STRING_ADD_FLAGS) { 6566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, FieldMemOperand(a0, HeapObject::kMapOffset)); 6567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset)); 6568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset)); 6569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(t1, FieldMemOperand(t1, Map::kInstanceTypeOffset)); 6570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label non_ascii, allocated, ascii_data; 6572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kTwoByteStringTag == 0); 65733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Branch to non_ascii if either string-encoding field is zero (non-ASCII). 6574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t4, t0, Operand(t1)); 6575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t4, t4, Operand(kStringEncodingMask)); 6576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&non_ascii, eq, t4, Operand(zero_reg)); 6577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate an ASCII cons string. 6579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&ascii_data); 65803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateAsciiConsString(v0, t2, t0, t1, &call_runtime); 6581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&allocated); 6582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fill the fields of the cons string. 65833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a0, FieldMemOperand(v0, ConsString::kFirstOffset)); 65843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a1, FieldMemOperand(v0, ConsString::kSecondOffset)); 6585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->string_add_native(), 1, a2, a3); 65863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(2); 6587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&non_ascii); 6589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // At least one of the strings is two-byte. Check whether it happens 6590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // to contain only ASCII characters. 6591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t0: first instance type. 6592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t1: second instance type. 6593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Branch to if _both_ instances have kAsciiDataHintMask set. 6594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(at, t0, Operand(kAsciiDataHintMask)); 6595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ and_(at, at, t1); 6596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&ascii_data, ne, at, Operand(zero_reg)); 6597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xor_(t0, t0, t1); 6599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); 6600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t0, t0, Operand(kAsciiStringTag | kAsciiDataHintTag)); 6601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&ascii_data, eq, t0, Operand(kAsciiStringTag | kAsciiDataHintTag)); 6602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a two byte cons string. 66043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateTwoByteConsString(v0, t2, t0, t1, &call_runtime); 6605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&allocated); 6606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 66073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We cannot encounter sliced strings or cons strings here since: 66083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength); 66093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle creating a flat result from either external or sequential strings. 66103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Locate the first characters' locations. 6611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: first string 6612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: second string 6613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: length of first string 6614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: length of second string 6615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t0: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) 6616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t1: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) 6617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t2: sum of lengths. 66183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label first_prepared, second_prepared; 6619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&string_add_flat_result); 6620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (flags_ != NO_STRING_ADD_FLAGS) { 6621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, FieldMemOperand(a0, HeapObject::kMapOffset)); 6622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset)); 6623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset)); 6624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(t1, FieldMemOperand(t1, Map::kInstanceTypeOffset)); 6625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 66263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check whether both strings have same encoding 66273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Xor(t3, t0, Operand(t1)); 66283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t3, t3, Operand(kStringEncodingMask)); 66293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&call_runtime, ne, t3, Operand(zero_reg)); 66303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSeqStringTag == 0); 66323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t4, t0, Operand(kStringRepresentationMask)); 6633c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 66343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); 66353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label skip_first_add; 66363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&skip_first_add, ne, t4, Operand(zero_reg)); 66373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(USE_DELAY_SLOT, &first_prepared); 66383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addiu(t3, a0, SeqAsciiString::kHeaderSize - kHeapObjectTag); 66393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&skip_first_add); 66403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // External string: rule out short external string and load string resource. 66413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kShortExternalStringTag != 0); 66423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t4, t0, Operand(kShortExternalStringMask)); 66433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&call_runtime, ne, t4, Operand(zero_reg)); 66443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t3, FieldMemOperand(a0, ExternalString::kResourceDataOffset)); 66453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&first_prepared); 66463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 66473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSeqStringTag == 0); 66483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t4, t1, Operand(kStringRepresentationMask)); 66493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); 66503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label skip_second_add; 66513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&skip_second_add, ne, t4, Operand(zero_reg)); 66523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(USE_DELAY_SLOT, &second_prepared); 66533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addiu(a1, a1, SeqAsciiString::kHeaderSize - kHeapObjectTag); 66543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&skip_second_add); 66553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // External string: rule out short external string and load string resource. 66563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kShortExternalStringTag != 0); 66573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t4, t1, Operand(kShortExternalStringMask)); 66583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&call_runtime, ne, t4, Operand(zero_reg)); 66593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a1, FieldMemOperand(a1, ExternalString::kResourceDataOffset)); 66603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&second_prepared); 66613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 66623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label non_ascii_string_add_flat_result; 66633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // t3: first character of first string 66643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1: first character of second string 6665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: length of first string 6666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: length of second string 6667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t2: sum of lengths. 66683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Both strings have the same encoding. 66693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kTwoByteStringTag == 0); 66703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(t4, t1, Operand(kStringEncodingMask)); 66713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&non_ascii_string_add_flat_result, eq, t4, Operand(zero_reg)); 66723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 66733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateAsciiString(v0, t2, t0, t1, t5, &call_runtime); 66743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(t2, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 66753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // v0: result string. 66763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // t3: first character of first string. 66773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1: first character of second string 6678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: length of first string. 6679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: length of second string. 6680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t2: first character of result. 6681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 66823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringHelper::GenerateCopyCharacters(masm, t2, t3, a2, t0, true); 6683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t2: next character of result. 6684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringHelper::GenerateCopyCharacters(masm, t2, a1, a3, t0, true); 6685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->string_add_native(), 1, a2, a3); 66863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(2); 6687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&non_ascii_string_add_flat_result); 66893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateTwoByteString(v0, t2, t0, t1, t5, &call_runtime); 66903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(t2, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 66913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // v0: result string. 66923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // t3: first character of first string. 66933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a1: first character of second string. 6694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: length of first string. 6695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: length of second string. 6696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t2: first character of result. 66973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringHelper::GenerateCopyCharacters(masm, t2, t3, a2, t0, false); 66983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // t2: next character of result. 6699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringHelper::GenerateCopyCharacters(masm, t2, a1, a3, t0, false); 6700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->string_add_native(), 1, a2, a3); 67023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DropAndRet(2); 6703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Just jump to runtime to add the two strings. 67053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&call_runtime); 6706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 6707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (call_builtin.is_linked()) { 6709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_builtin); 6710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); 6711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid StringAddStub::GenerateConvertArgument(MacroAssembler* masm, 6716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int stack_offset, 6717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register arg, 6718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 6719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2, 6720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch3, 6721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch4, 6722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* slow) { 6723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // First check if the argument is already a string. 6724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_string, done; 6725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(arg, ¬_string); 6726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(arg, scratch1, scratch1); 6727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, lt, scratch1, Operand(FIRST_NONSTRING_TYPE)); 6728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the number to string cache. 6730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_cached; 6731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_string); 6732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Puts the cached result into scratch1. 6733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NumberToStringStub::GenerateLookupNumberStringCache(masm, 6734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch arg, 6735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 6736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 6737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch3, 6738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch4, 6739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch false, 6740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ¬_cached); 6741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(arg, scratch1); 6742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(arg, MemOperand(sp, stack_offset)); 6743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done); 6744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the argument is a safe string wrapper. 6746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_cached); 6747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(arg, slow); 6748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(arg, scratch1, scratch2); // map -> scratch1. 6749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(slow, ne, scratch2, Operand(JS_VALUE_TYPE)); 6750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(scratch2, FieldMemOperand(scratch1, Map::kBitField2Offset)); 6751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(scratch4, 1 << Map::kStringWrapperSafeForDefaultValueOf); 6752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch2, scratch2, scratch4); 6753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(slow, ne, scratch2, Operand(scratch4)); 6754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(arg, FieldMemOperand(arg, JSValue::kValueOffset)); 6755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(arg, MemOperand(sp, stack_offset)); 6756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 675844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 675944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 676044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 676144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid ICCompareStub::GenerateSmis(MacroAssembler* masm) { 6762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(state_ == CompareIC::SMIS); 6763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 6764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(a2, a1, a0); 6765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(a2, &miss); 6766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (GetCondition() == eq) { 6768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For equality we do not care about the sign of the result. 6769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(v0, a0, a1); 6770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Untag before subtracting to avoid handling overflow. 6772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(a1); 6773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(a0); 6774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(v0, a1, a0); 6775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 6777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 6779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateMiss(masm); 678044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 678144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 678244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 678344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { 6784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(state_ == CompareIC::HEAP_NUMBERS); 6785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label generic_stub; 67873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label unordered, maybe_undefined1, maybe_undefined2; 6788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 6789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a2, a1, Operand(a0)); 6790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a2, &generic_stub); 6791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a0, a2, a2); 67933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&maybe_undefined1, ne, a2, Operand(HEAP_NUMBER_TYPE)); 6794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a1, a2, a2); 67953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE)); 6796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Inlining the double comparison and falling back to the general compare 6798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // stub if NaN is involved or FPU is unsupported. 6799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 6800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 6801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load left and right operand. 6803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(a2, a1, Operand(kHeapObjectTag)); 6804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f0, MemOperand(a2, HeapNumber::kValueOffset)); 6805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(a2, a0, Operand(kHeapObjectTag)); 6806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f2, MemOperand(a2, HeapNumber::kValueOffset)); 6807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 68083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Return a result of -1, 0, or 1, or use CompareStub for NaNs. 68093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fpu_eq, fpu_lt; 68103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test if equal, and also handle the unordered/NaN case. 68113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(&fpu_eq, &unordered, eq, f0, f2); 6812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 68133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test if less (unordered case is already handled). 68143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ BranchF(&fpu_lt, NULL, lt, f0, f2); 681585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 68163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Otherwise it's greater, so just fall thru, and return. 68173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(v0, Operand(GREATER)); 68183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 6819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&fpu_eq); 68215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ li(v0, Operand(EQUAL)); 68225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ Ret(); 6823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&fpu_lt); 68255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ li(v0, Operand(LESS)); 68265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ Ret(); 682785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 68285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 68293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&unordered); 68303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, a1, a0); 6832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&generic_stub); 6833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 6834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 68353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&maybe_undefined1); 68363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (Token::IsOrderedRelationalCompareOp(op_)) { 68373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 68383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, a0, Operand(at)); 68393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ GetObjectType(a1, a2, a2); 68403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE)); 68413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&unordered); 68423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 68433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 68443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&maybe_undefined2); 68453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (Token::IsOrderedRelationalCompareOp(op_)) { 68463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 68473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&unordered, eq, a1, Operand(at)); 68483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 68493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 6851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateMiss(masm); 6852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid ICCompareStub::GenerateSymbols(MacroAssembler* masm) { 6856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(state_ == CompareIC::SYMBOLS); 6857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 6858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers containing left and right operands respectively. 6860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = a1; 6861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right = a0; 6862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp1 = a2; 6863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp2 = a3; 6864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both operands are heap objects. 6866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfEitherSmi(left, right, &miss); 6867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both operands are symbols. 6869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 6870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 6871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 6872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 6873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSymbolTag != 0); 6874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(tmp1, tmp1, Operand(tmp2)); 6875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(tmp1, tmp1, kIsSymbolMask); 6876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&miss, eq, tmp1, Operand(zero_reg)); 6877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure a0 is non-zero. At this point input operands are 6878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // guaranteed to be non-zero. 6879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(right.is(a0)); 6880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(EQUAL == 0); 6881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 6882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, right); 6883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Symbols are compared by identity. 6884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(ne, left, Operand(right)); 6885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(Smi::FromInt(EQUAL))); 6886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 6887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 6889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateMiss(masm); 6890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid ICCompareStub::GenerateStrings(MacroAssembler* masm) { 6894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(state_ == CompareIC::STRINGS); 6895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 6896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 68973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool equality = Token::IsEqualityOp(op_); 68983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers containing left and right operands respectively. 6900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = a1; 6901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right = a0; 6902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp1 = a2; 6903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp2 = a3; 6904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp3 = t0; 6905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp4 = t1; 6906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp5 = t2; 6907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both operands are heap objects. 6909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfEitherSmi(left, right, &miss); 6910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both operands are strings. This leaves the instance 6912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // types loaded in tmp1 and tmp2. 6913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 6914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 6915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 6916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 6917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kNotStringTag != 0); 6918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(tmp3, tmp1, tmp2); 6919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(tmp5, tmp3, Operand(kIsNotStringMask)); 6920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&miss, ne, tmp5, Operand(zero_reg)); 6921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fast check for identical strings. 6923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label left_ne_right; 6924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(EQUAL == 0); 6925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 69263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&left_ne_right, ne, left, Operand(right)); 69273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 6928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, zero_reg); // In the delay slot. 6929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&left_ne_right); 6930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle not identical strings. 6932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both strings are symbols. If they are, we're done 6934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // because we already know they are not identical. 69353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (equality) { 69363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(GetCondition() == eq); 69373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSymbolTag != 0); 69383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(tmp3, tmp1, Operand(tmp2)); 69393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(tmp5, tmp3, Operand(kIsSymbolMask)); 69403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label is_symbol; 69413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&is_symbol, eq, tmp5, Operand(zero_reg)); 69423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure a0 is non-zero. At this point input operands are 69433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // guaranteed to be non-zero. 69443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(right.is(a0)); 69453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 69463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(v0, a0); // In the delay slot. 69473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&is_symbol); 69483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 6949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both strings are sequential ASCII. 6951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label runtime; 69523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfBothInstanceTypesAreNotSequentialAscii( 69533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch tmp1, tmp2, tmp3, tmp4, &runtime); 6954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare flat ASCII strings. Returns when done. 69563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (equality) { 69573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCompareStub::GenerateFlatAsciiStringEquals( 69583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, left, right, tmp1, tmp2, tmp3); 69593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 69603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCompareStub::GenerateCompareFlatAsciiStrings( 69613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, left, right, tmp1, tmp2, tmp3, tmp4); 69623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 6963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle more complex cases in runtime. 6965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&runtime); 6966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(left, right); 69673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (equality) { 69683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallRuntime(Runtime::kStringEquals, 2, 1); 69693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 69703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 69713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 6972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 6974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateMiss(masm); 697544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 697644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 697744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 697844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid ICCompareStub::GenerateObjects(MacroAssembler* masm) { 6979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(state_ == CompareIC::OBJECTS); 6980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 6981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a2, a1, Operand(a0)); 6982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a2, &miss); 6983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a0, a2, a2); 6985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); 6986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a1, a2, a2); 6987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&miss, ne, a2, Operand(JS_OBJECT_TYPE)); 6988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(GetCondition() == eq); 69903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 69913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ subu(v0, a0, a1); 6992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 6994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateMiss(masm); 699544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 699644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 699744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 69983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { 69993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss; 70003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(a2, a1, a0); 70013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(a2, &miss); 70023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a2, FieldMemOperand(a0, HeapObject::kMapOffset)); 70033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset)); 70043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, a2, Operand(known_map_)); 70053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, a3, Operand(known_map_)); 700685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 70073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 70083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ subu(v0, a0, a1); 70093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&miss); 70113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMiss(masm); 70123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 70133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ICCompareStub::GenerateMiss(MacroAssembler* masm) { 70153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 70163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call the runtime system in a fresh internal frame. 70173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference miss = 70183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate()); 70193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 70203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(a1, a0); 70213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(ra); 70223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(a1, a0); 70233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(t0, Operand(Smi::FromInt(op_))); 70243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addiu(sp, sp, -kPointerSize); 70253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallExternalReference(miss, 3, USE_DELAY_SLOT); 70263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(t0, MemOperand(sp)); // In the delay slot. 70273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the entry point of the rewritten stub. 70283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(a2, v0, Operand(Code::kHeaderSize - kHeapObjectTag)); 70293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore registers. 70303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Pop(a1, a0, ra); 70313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 7032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(a2); 703344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 703444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 70353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid DirectCEntryStub::Generate(MacroAssembler* masm) { 7037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // No need to pop or drop anything, LeaveExitFrame will restore the old 7038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // stack, thus dropping the allocated space for the return value. 7039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The saved ra is after the reserved stack space for the 4 args. 7040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t9, MemOperand(sp, kCArgsSlotsSize)); 7041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 70423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code && FLAG_enable_slow_asserts) { 7043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // In case of an error the return address may point to a memory area 7044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // filled with kZapValue by the GC. 7045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Dereference the address and check for this. 7046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, MemOperand(t9)); 7047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Assert(ne, "Received invalid return address.", t0, 7048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(reinterpret_cast<uint32_t>(kZapValue))); 7049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(t9); 7051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 705244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid DirectCEntryStub::GenerateCall(MacroAssembler* masm, 7055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference function) { 7056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t9, Operand(function)); 7057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch this->GenerateCall(masm, t9); 7058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 7059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 70603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid DirectCEntryStub::GenerateCall(MacroAssembler* masm, 7062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register target) { 7063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(t9, target); 7064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AssertStackIsAligned(); 7065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate space for arg slots. 7066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(sp, sp, kCArgsSlotsSize); 7067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Block the trampoline pool through the whole function to make sure the 7069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // number of generated instructions is constant. 7070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); 7071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We need to get the current 'pc' value, which is not available on MIPS. 7073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label find_ra; 7074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->bal(&find_ra); // ra = pc + 8. 7075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->nop(); // Branch delay slot nop. 7076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->bind(&find_ra); 7077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kNumInstructionsToJump = 6; 7079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->addiu(ra, ra, kNumInstructionsToJump * kPointerSize); 7080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Push return address (accessible to GC through exit frame pc). 7081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This spot for ra was reserved in EnterExitFrame. 7082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->sw(ra, MemOperand(sp, kCArgsSlotsSize)); 70833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->li(ra, 70843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(reinterpret_cast<intptr_t>(GetCode().location()), 70853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::CODE_TARGET), 70863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CONSTANT_SIZE); 7087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call the function. 7088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->Jump(t9); 7089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure the stored 'ra' points to this position. 7090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(kNumInstructionsToJump, masm->InstructionsGeneratedSince(&find_ra)); 7091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 7092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 70943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, 70953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss, 70963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* done, 70973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 70983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register properties, 70993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 71003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0) { 71013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If names of slots in range from 1 to kProbes - 1 for the hash value are 7102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // not equal to the name and kProbes-th slot is not used (its name is the 7103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // undefined value), it guarantees the hash table doesn't contain the 7104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // property. It's true even if some slots represent deleted properties 71053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // (their names are the hole value). 7106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < kInlinedProbes; i++) { 7107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // scratch0 points to properties hash. 7108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute the masked index: (hash + i + i * i) & mask. 7109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register index = scratch0; 7110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Capacity is smi 2^n. 7111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(index, FieldMemOperand(properties, kCapacityOffset)); 7112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(index, index, Operand(1)); 7113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(index, index, Operand( 71143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i)))); 7115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Scale the index by multiplying by the entry size. 7117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(StringDictionary::kEntrySize == 3); 71183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(at, index, 1); 7119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(index, index, at); 7120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register entity_name = scratch0; 7122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Having undefined at this place means the name is not contained. 7123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(kSmiTagSize, 1); 7124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp = properties; 7125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(scratch0, index, 1); 7126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(tmp, properties, scratch0); 7127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); 7128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!tmp.is(entity_name)); 7130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); 7131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(done, eq, entity_name, Operand(tmp)); 7132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i != kInlinedProbes - 1) { 71343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the hole ready for use below: 71353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); 71363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stop if found the property. 7138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(miss, eq, entity_name, Operand(Handle<String>(name))); 7139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 71403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label the_hole; 71413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&the_hole, eq, entity_name, Operand(tmp)); 71423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the entry name is not a symbol. 7144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); 7145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(entity_name, 7146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); 7147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch0, entity_name, Operand(kIsSymbolMask)); 7148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(miss, eq, scratch0, Operand(zero_reg)); 7149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 71503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&the_hole); 71513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore the properties. 7153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(properties, 7154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 7155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int spill_mask = 7159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (ra.bit() | t2.bit() | t1.bit() | t0.bit() | a3.bit() | 71603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a2.bit() | a1.bit() | a0.bit() | v0.bit()); 7161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ MultiPush(spill_mask); 7163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 7164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a1, Operand(Handle<String>(name))); 7165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringDictionaryLookupStub stub(NEGATIVE_LOOKUP); 71663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 71673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(at, v0); 7168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ MultiPop(spill_mask); 7169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 71703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(done, eq, at, Operand(zero_reg)); 71713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(miss, ne, at, Operand(zero_reg)); 7172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 7173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Probe the string dictionary in the |elements| register. Jump to the 7176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// |done| label if a property with the given name is found. Jump to 7177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// the |miss| label otherwise. 7178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// If lookup was successful |scratch2| will be equal to elements + 4 * index. 7179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, 7180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* miss, 7181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* done, 7182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register elements, 7183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register name, 7184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 7185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2) { 71863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!elements.is(scratch1)); 71873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!elements.is(scratch2)); 71883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!name.is(scratch1)); 71893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!name.is(scratch2)); 71903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Assert that name contains a string. 7192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (FLAG_debug_code) __ AbortIfNotString(name); 7193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute the capacity mask. 7195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, FieldMemOperand(elements, kCapacityOffset)); 7196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(scratch1, scratch1, kSmiTagSize); // convert smi to int 7197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(scratch1, scratch1, Operand(1)); 7198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Generate an unrolled loop that performs a few probes before 7200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // giving up. Measurements done on Gmail indicate that 2 probes 7201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // cover ~93% of loads from dictionaries. 7202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < kInlinedProbes; i++) { 7203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute the masked index: (hash + i + i * i) & mask. 7204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch2, FieldMemOperand(name, String::kHashFieldOffset)); 7205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i > 0) { 7206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Add the probe offset (i + i * i) left shifted to avoid right shifting 7207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the hash in a separate instruction. The value hash + i + i * i is right 7208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // shifted in the following and instruction. 7209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(StringDictionary::GetProbeOffset(i) < 7210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1 << (32 - String::kHashFieldOffset)); 7211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch2, scratch2, Operand( 7212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringDictionary::GetProbeOffset(i) << String::kHashShift)); 7213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(scratch2, scratch2, String::kHashShift); 7215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch2, scratch1, scratch2); 7216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Scale the index by multiplying by the element size. 7218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(StringDictionary::kEntrySize == 3); 7219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // scratch2 = scratch2 * 3. 7220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 72213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(at, scratch2, 1); 7222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch2, scratch2, at); 7223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the key is identical to the name. 7225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(at, scratch2, 2); 7226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(scratch2, elements, at); 7227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(at, FieldMemOperand(scratch2, kElementsStartOffset)); 7228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(done, eq, name, Operand(at)); 7229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int spill_mask = 7232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (ra.bit() | t2.bit() | t1.bit() | t0.bit() | 72333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a3.bit() | a2.bit() | a1.bit() | a0.bit() | v0.bit()) & 7234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ~(scratch1.bit() | scratch2.bit()); 7235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ MultiPush(spill_mask); 72373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (name.is(a0)) { 72383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!elements.is(a1)); 72393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(a1, name); 72403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(a0, elements); 72413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 72423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(a0, elements); 72433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(a1, name); 72443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 7245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringDictionaryLookupStub stub(POSITIVE_LOOKUP); 7246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CallStub(&stub); 7247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(scratch2, a2); 72483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(at, v0); 7249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ MultiPop(spill_mask); 7250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 72513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(done, ne, at, Operand(zero_reg)); 72523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(miss, eq, at, Operand(zero_reg)); 7253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 7254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid StringDictionaryLookupStub::Generate(MacroAssembler* masm) { 72573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This stub overrides SometimesSetsUpAFrame() to return false. That means 72583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // we cannot call anything that could cause a GC from this stub. 7259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers: 7260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // result: StringDictionary to probe 7261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: key 7262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // : StringDictionary to probe. 7263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // index_: will hold an index of entry if lookup is successful. 7264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // might alias with result_. 7265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Returns: 7266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // result_ is zero if lookup failed, non zero otherwise. 7267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result = v0; 7269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dictionary = a0; 7270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register key = a1; 7271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register index = a2; 7272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register mask = a3; 7273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register hash = t0; 7274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register undefined = t1; 7275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register entry_key = t2; 7276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label in_dictionary, maybe_in_dictionary, not_in_dictionary; 7278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(mask, FieldMemOperand(dictionary, kCapacityOffset)); 7280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(mask, mask, kSmiTagSize); 7281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(mask, mask, Operand(1)); 7282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(hash, FieldMemOperand(key, String::kHashFieldOffset)); 7284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); 7286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = kInlinedProbes; i < kTotalProbes; i++) { 7288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute the masked index: (hash + i + i * i) & mask. 7289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Capacity is smi 2^n. 7290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i > 0) { 7291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Add the probe offset (i + i * i) left shifted to avoid right shifting 7292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the hash in a separate instruction. The value hash + i + i * i is right 7293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // shifted in the following and instruction. 7294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(StringDictionary::GetProbeOffset(i) < 7295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1 << (32 - String::kHashFieldOffset)); 7296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(index, hash, Operand( 7297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringDictionary::GetProbeOffset(i) << String::kHashShift)); 7298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 7299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(index, hash); 7300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(index, index, String::kHashShift); 7302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(index, mask, index); 7303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Scale the index by multiplying by the entry size. 7305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(StringDictionary::kEntrySize == 3); 7306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // index *= 3. 7307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(at, index); 7308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(index, index, 1); 7309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(index, index, at); 7310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(kSmiTagSize, 1); 7313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(index, index, 2); 7314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(index, index, dictionary); 7315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(entry_key, FieldMemOperand(index, kElementsStartOffset)); 7316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Having undefined at this place means the name is not contained. 7318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_in_dictionary, eq, entry_key, Operand(undefined)); 7319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stop if found the property. 7321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&in_dictionary, eq, entry_key, Operand(key)); 7322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { 7324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the entry name is not a symbol. 7325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); 7326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(entry_key, 7327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); 7328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(result, entry_key, Operand(kIsSymbolMask)); 7329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&maybe_in_dictionary, eq, result, Operand(zero_reg)); 7330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&maybe_in_dictionary); 7334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If we are doing negative lookup then probing failure should be 7335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // treated as a lookup success. For positive lookup probing failure 7336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // should be treated as lookup failure. 7337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (mode_ == POSITIVE_LOOKUP) { 73383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 7339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(result, zero_reg); 7340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&in_dictionary); 73433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 7344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(result, 1); 7345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_in_dictionary); 73473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 7348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(result, zero_reg); 73493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 73503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 73513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 73523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct AheadOfTimeWriteBarrierStubList { 73533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, value, address; 73543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction action; 73553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}; 73563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7357db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch#define REG(Name) { kRegister_ ## Name ## _Code } 73583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7359db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdochstatic const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { 73603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Used in RegExpExecStub. 7361db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(s2), REG(s0), REG(t3), EMIT_REMEMBERED_SET }, 7362db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(s2), REG(a2), REG(t3), EMIT_REMEMBERED_SET }, 73633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Used in CompileArrayPushCall. 73643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. 73653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Also used in KeyedStoreIC::GenerateGeneric. 7366db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(a3), REG(t0), REG(t1), EMIT_REMEMBERED_SET }, 73673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Used in CompileStoreGlobal. 7368db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(t0), REG(a1), REG(a2), OMIT_REMEMBERED_SET }, 73693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. 7370db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(a1), REG(a2), REG(a3), EMIT_REMEMBERED_SET }, 7371db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(a3), REG(a2), REG(a1), EMIT_REMEMBERED_SET }, 73723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. 7373db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(a2), REG(a1), REG(a3), EMIT_REMEMBERED_SET }, 7374db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(a3), REG(a1), REG(a2), EMIT_REMEMBERED_SET }, 73753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // KeyedStoreStubCompiler::GenerateStoreFastElement. 7376db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(a3), REG(a2), REG(t0), EMIT_REMEMBERED_SET }, 7377db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(a2), REG(a3), REG(t0), EMIT_REMEMBERED_SET }, 73783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ElementsTransitionGenerator::GenerateSmiOnlyToObject 73793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and ElementsTransitionGenerator::GenerateSmiOnlyToDouble 73803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and ElementsTransitionGenerator::GenerateDoubleToObject 7381db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(a2), REG(a3), REG(t5), EMIT_REMEMBERED_SET }, 7382db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(a2), REG(a3), REG(t5), OMIT_REMEMBERED_SET }, 73833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ElementsTransitionGenerator::GenerateDoubleToObject 7384db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(t2), REG(a2), REG(a0), EMIT_REMEMBERED_SET }, 7385db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(a2), REG(t2), REG(t5), EMIT_REMEMBERED_SET }, 73863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // StoreArrayLiteralElementStub::Generate 7387db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(t1), REG(a0), REG(t2), EMIT_REMEMBERED_SET }, 73883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Null termination. 7389db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET} 73903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}; 73913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7392db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch#undef REG 7393db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch 73943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 73953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool RecordWriteStub::IsPregenerated() { 7396db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; 73973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !entry->object.is(no_reg); 73983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch entry++) { 73993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object_.is(entry->object) && 74003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value_.is(entry->value) && 74013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_.is(entry->address) && 74023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch remembered_set_action_ == entry->action && 74033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch save_fp_regs_mode_ == kDontSaveFPRegs) { 74043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 74053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 74063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 74073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 74083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 74093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool StoreBufferOverflowStub::IsPregenerated() { 74123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return save_doubles_ == kDontSaveFPRegs || ISOLATE->fp_stubs_generated(); 74133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 74143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime() { 74173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StoreBufferOverflowStub stub1(kDontSaveFPRegs); 74183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub1.GetCode()->set_is_pregenerated(true); 74193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 74203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RecordWriteStub::GenerateFixedRegStubsAheadOfTime() { 7423db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; 74243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !entry->object.is(no_reg); 74253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch entry++) { 74263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWriteStub stub(entry->object, 74273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch entry->value, 74283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch entry->address, 74293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch entry->action, 74303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 74313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub.GetCode()->set_is_pregenerated(true); 74323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 74333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 74343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Takes the input in 3 registers: address_ value_ and object_. A pointer to 74373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// the value has just been written into the object, now this stub makes sure 74383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// we keep the GC informed. The word in the object where the value has been 74393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// written is in the address register. 74403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RecordWriteStub::Generate(MacroAssembler* masm) { 74413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label skip_to_incremental_noncompacting; 74423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label skip_to_incremental_compacting; 74433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The first two branch+nop instructions are generated with labels so as to 74453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // get the offset fixed up correctly by the bind(Label*) call. We patch it 74463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // back and forth between a "bne zero_reg, zero_reg, ..." (a nop in this 74473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // position) and the "beq zero_reg, zero_reg, ..." when we start and stop 74483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // incremental heap marking. 74493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // See RecordWriteStub::Patch for details. 74503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ beq(zero_reg, zero_reg, &skip_to_incremental_noncompacting); 74513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ nop(); 74523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ beq(zero_reg, zero_reg, &skip_to_incremental_compacting); 74533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ nop(); 74543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (remembered_set_action_ == EMIT_REMEMBERED_SET) { 74563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RememberedSetHelper(object_, 74573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_, 74583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value_, 74593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch save_fp_regs_mode_, 74603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler::kReturnAtEnd); 74613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 74623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 74633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&skip_to_incremental_noncompacting); 74653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateIncremental(masm, INCREMENTAL); 74663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&skip_to_incremental_compacting); 74683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateIncremental(masm, INCREMENTAL_COMPACTION); 74693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. 74713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Will be checked in IncrementalMarking::ActivateGeneratedStub. 74723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PatchBranchIntoNop(masm, 0); 74743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PatchBranchIntoNop(masm, 2 * Assembler::kInstrSize); 74753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 74763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { 74793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.Save(masm); 74803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (remembered_set_action_ == EMIT_REMEMBERED_SET) { 74823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label dont_need_remembered_set; 74833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(regs_.scratch0(), MemOperand(regs_.address(), 0)); 74853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. 74863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch0(), 74873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &dont_need_remembered_set); 74883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckPageFlag(regs_.object(), 74903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch0(), 74913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1 << MemoryChunk::SCAN_ON_SCAVENGE, 74923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ne, 74933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &dont_need_remembered_set); 74943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First notify the incremental marker if necessary, then update the 74963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // remembered set. 74973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckNeedsToInformIncrementalMarker( 74983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); 74993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InformIncrementalMarker(masm, mode); 75003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.Restore(masm); 75013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RememberedSetHelper(object_, 75023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_, 75033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value_, 75043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch save_fp_regs_mode_, 75053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler::kReturnAtEnd); 75063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&dont_need_remembered_set); 75083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 75093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckNeedsToInformIncrementalMarker( 75113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, kReturnOnNoNeedToInformIncrementalMarker, mode); 75123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InformIncrementalMarker(masm, mode); 75133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.Restore(masm); 7514592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Ret(); 7515592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 7516592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 7517592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 75183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) { 75193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); 75203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int argument_count = 3; 75213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(argument_count, regs_.scratch0()); 75223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address = 75233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a0.is(regs_.address()) ? regs_.scratch0() : regs_.address(); 75243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!address.is(regs_.object())); 75253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!address.is(a0)); 75263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(address, regs_.address()); 75273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(a0, regs_.object()); 75283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mode == INCREMENTAL_COMPACTION) { 75293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(a1, address); 75303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 75313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(mode == INCREMENTAL); 75323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a1, MemOperand(address, 0)); 75333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 75343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a2, Operand(ExternalReference::isolate_address())); 75353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 75373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mode == INCREMENTAL_COMPACTION) { 75383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction( 75393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::incremental_evacuation_record_write_function( 75403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()), 75413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch argument_count); 75423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 75433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(mode == INCREMENTAL); 75443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction( 75453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::incremental_marking_record_write_function( 75463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()), 75473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch argument_count); 75483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 75493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); 75503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 75513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RecordWriteStub::CheckNeedsToInformIncrementalMarker( 75543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 75553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OnNoNeedToInformIncrementalMarker on_no_need, 75563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Mode mode) { 75573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label on_black; 75583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label need_incremental; 75593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label need_incremental_pop_scratch; 75603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Let's look at the color of the object: If it is not black we don't have 75623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // to inform the incremental marker. 75633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black); 75643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.Restore(masm); 75663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 75673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RememberedSetHelper(object_, 75683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_, 75693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value_, 75703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch save_fp_regs_mode_, 75713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler::kReturnAtEnd); 75723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 75733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 75743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 75753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&on_black); 75773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the value from the slot. 75793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(regs_.scratch0(), MemOperand(regs_.address(), 0)); 75803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mode == INCREMENTAL_COMPACTION) { 75823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ensure_not_white; 75833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckPageFlag(regs_.scratch0(), // Contains value. 75853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch1(), // Scratch. 75863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemoryChunk::kEvacuationCandidateMask, 75873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eq, 75883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &ensure_not_white); 75893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckPageFlag(regs_.object(), 75913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch1(), // Scratch. 75923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemoryChunk::kSkipEvacuationSlotsRecordingMask, 75933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eq, 75943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &need_incremental); 75953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&ensure_not_white); 75973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 75983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We need extra registers for this, so we push the object and the address 76003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // register temporarily. 76013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(regs_.object(), regs_.address()); 76023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ EnsureNotWhite(regs_.scratch0(), // The value. 76033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch1(), // Scratch. 76043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.object(), // Scratch. 76053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.address(), // Scratch. 76063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &need_incremental_pop_scratch); 76073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Pop(regs_.object(), regs_.address()); 76083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.Restore(masm); 76103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 76113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RememberedSetHelper(object_, 76123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_, 76133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value_, 76143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch save_fp_regs_mode_, 76153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler::kReturnAtEnd); 76163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 76173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 76183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 76193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&need_incremental_pop_scratch); 76213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Pop(regs_.object(), regs_.address()); 76223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&need_incremental); 76243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fall through when we need to inform the incremental marker. 76263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 76273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { 76303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------- S t a t e ------------- 76313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- a0 : element value to store 76323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- a1 : array literal 76333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- a2 : map of array literal 76343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- a3 : element index as smi 76353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- t0 : array literal index in function as smi 76363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------------------------------- 76373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label element_done; 76393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label double_elements; 76403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label smi_element; 76413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label slow_elements; 76423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fast_elements; 76433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastElements(a2, t1, &double_elements); 76453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS 76463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(a0, &smi_element); 76473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastSmiOnlyElements(a2, t1, &fast_elements); 76483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store into the array literal requires a elements transition. Call into 76503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the runtime. 76513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow_elements); 76523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // call. 76533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(a1, a3, a0); 76543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 76553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t1, FieldMemOperand(t1, JSFunction::kLiteralsOffset)); 76563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(t1, t0); 76573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1); 76583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Array literal has ElementsKind of FAST_ELEMENTS and value is an object. 76603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_elements); 76613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset)); 76623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(t2, a3, kPointerSizeLog2 - kSmiTagSize); 76633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(t2, t1, t2); 76643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(t2, t2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 76653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a0, MemOperand(t2, 0)); 76663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier for the array store. 76673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(t1, t2, a0, kRAHasNotBeenSaved, kDontSaveFPRegs, 76683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 76693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 76703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(v0, a0); 76713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or 76733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FAST_ELEMENTS, and value is Smi. 76743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&smi_element); 76753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset)); 76763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(t2, a3, kPointerSizeLog2 - kSmiTagSize); 76773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(t2, t1, t2); 76783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a0, FieldMemOperand(t2, FixedArray::kHeaderSize)); 76793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 76803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(v0, a0); 76813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. 76833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&double_elements); 76843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset)); 76853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ StoreNumberToDoubleElements(a0, a3, a1, t1, t2, t3, t5, a2, 76863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &slow_elements); 76873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 76883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(v0, a0); 76893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 76903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 769244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef __ 769344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 769444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} } // namespace v8::internal 769544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 769644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif // V8_TARGET_ARCH_MIPS 7697