1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64 880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/handler-compiler.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate.h" 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/jsregexp.h" 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/regexp-macro-assembler.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/runtime.h" 1880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 2180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InitializeArrayConstructorDescriptor( 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate, CodeStubDescriptor* descriptor, 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int constant_stack_parameter_count) { 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address deopt_handler = Runtime::FunctionForId( 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Runtime::kArrayConstructor)->entry; 2880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (constant_stack_parameter_count == 0) { 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch descriptor->Initialize(deopt_handler, constant_stack_parameter_count, 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JS_FUNCTION_STUB_MODE); 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch descriptor->Initialize(rax, deopt_handler, constant_stack_parameter_count, 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); 3580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 3680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 3780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InitializeInternalArrayConstructorDescriptor( 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate, CodeStubDescriptor* descriptor, 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int constant_stack_parameter_count) { 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address deopt_handler = Runtime::FunctionForId( 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Runtime::kInternalArrayConstructor)->entry; 443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (constant_stack_parameter_count == 0) { 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch descriptor->Initialize(deopt_handler, constant_stack_parameter_count, 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JS_FUNCTION_STUB_MODE); 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch descriptor->Initialize(rax, deopt_handler, constant_stack_parameter_count, 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); 513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayNoArgumentConstructorStub::InitializeDescriptor( 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeStubDescriptor* descriptor) { 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InitializeArrayConstructorDescriptor(isolate(), descriptor, 0); 583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArraySingleArgumentConstructorStub::InitializeDescriptor( 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeStubDescriptor* descriptor) { 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InitializeArrayConstructorDescriptor(isolate(), descriptor, 1); 643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 65592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 66592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayNArgumentsConstructorStub::InitializeDescriptor( 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeStubDescriptor* descriptor) { 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InitializeArrayConstructorDescriptor(isolate(), descriptor, -1); 7080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 7180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 7280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArrayNoArgumentConstructorStub::InitializeDescriptor( 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeStubDescriptor* descriptor) { 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArraySingleArgumentConstructorStub::InitializeDescriptor( 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeStubDescriptor* descriptor) { 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1); 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 83257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 84257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArrayNArgumentsConstructorStub::InitializeDescriptor( 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeStubDescriptor* descriptor) { 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1); 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 8969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 9080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm) 9280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 9380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm, 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference miss) { 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the static counter each time a new code stub is generated. 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->counters()->code_stubs()->Increment(); 9880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor(); 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int param_count = descriptor.GetEnvironmentParameterCount(); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime system in a fresh internal frame. 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(param_count == 0 || 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rax.is(descriptor.GetEnvironmentParameterRegister(param_count - 1))); 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push arguments 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < param_count; ++i) { 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(descriptor.GetEnvironmentParameterRegister(i)); 10969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallExternalReference(miss, param_count); 11169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 11280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 11469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 11580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 11669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushCallerSaved(save_doubles() ? kSaveFPRegs : kDontSaveFPRegs); 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int argument_count = 1; 1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(argument_count); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadAddress(arg_reg_1, 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::isolate_address(isolate())); 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction( 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::store_buffer_overflow_function(isolate()), 1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch argument_count); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopCallerSaved(save_doubles() ? kSaveFPRegs : kDontSaveFPRegs); 1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass FloatingPointHelper : public AllStatic { 13480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public: 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum ConvertUndefined { 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CONVERT_UNDEFINED_TO_ZERO, 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BAILOUT_ON_UNDEFINED 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 13980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. 14080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If the operands are not both numbers, jump to not_numbers. 14180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Leaves rdx and rax unchanged. SmiOperands assumes both are smis. 14280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // NumberOperands assumes both are smis or heap numbers. 14380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen static void LoadSSE2UnknownOperands(MacroAssembler* masm, 14480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* not_numbers); 1458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}; 14680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 14780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid DoubleToIStub::Generate(MacroAssembler* masm) { 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg = this->source(); 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register final_result_reg = this->destination(); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_truncating()); 1523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label check_negative, process_64_bits, done; 154086aeeaae12517475c22695a200be45495516549Ben Murdoch 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int double_offset = offset(); 1561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Account for return address and saved regs if input is rsp. 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (input_reg.is(rsp)) double_offset += 3 * kRegisterSize; 159086aeeaae12517475c22695a200be45495516549Ben Murdoch 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand mantissa_operand(MemOperand(input_reg, double_offset)); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand exponent_operand(MemOperand(input_reg, 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double_offset + kDoubleSize / 2)); 1631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1; 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch_candidates[3] = { rbx, rdx, rdi }; 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < 3; i++) { 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch1 = scratch_candidates[i]; 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!final_result_reg.is(scratch1) && !input_reg.is(scratch1)) break; 1698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Since we must use rcx for shifts below, use some other register (rax) 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to calculate the result if ecx is the requested return register. 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_reg = final_result_reg.is(rcx) ? rax : final_result_reg; 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save ecx if it isn't the return register and therefore volatile, or if it 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is the return register, then save the temp register we use in its stead 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for the result. 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register save_reg = final_result_reg.is(rcx) ? rax : rcx; 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(scratch1); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(save_reg); 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool stash_exponent_copy = !input_reg.is(rsp); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movl(scratch1, mantissa_operand); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movsd(xmm0, mantissa_operand); 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movl(rcx, exponent_operand); 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stash_exponent_copy) __ pushq(rcx); 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ andl(rcx, Immediate(HeapNumber::kExponentMask)); 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shrl(rcx, Immediate(HeapNumber::kExponentShift)); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leal(result_reg, MemOperand(rcx, -HeapNumber::kExponentBias)); 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(result_reg, Immediate(HeapNumber::kMantissaBits)); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, &process_64_bits); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result is entirely in lower 32-bits of mantissa 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize; 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subl(rcx, Immediate(delta)); 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xorl(result_reg, result_reg); 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rcx, Immediate(31)); 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, &done); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shll_cl(scratch1); 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&check_negative); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&process_64_bits); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cvttsd2siq(result_reg, xmm0); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the double was negative, negate the integer result. 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_negative); 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movl(result_reg, scratch1); 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ negl(result_reg); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stash_exponent_copy) { 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(MemOperand(rsp, 0), Immediate(0)); 2128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(exponent_operand, Immediate(0)); 2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmovl(greater, result_reg, scratch1); 21680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore registers 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stash_exponent_copy) { 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(kDoubleSize)); 221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!final_result_reg.is(result_reg)) { 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(final_result_reg.is(rcx)); 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movl(final_result_reg, result_reg); 225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(save_reg); 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(scratch1); 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 22980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 23080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 23180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 23280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, 23380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* not_numbers) { 23480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done; 23580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load operand in rdx into xmm0, or branch to not_numbers. 23680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex); 23780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfSmi(rdx, &load_smi_rdx); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(FieldOperand(rdx, HeapObject::kMapOffset), rcx); 23980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, not_numbers); // Argument in rdx is not a number. 24080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); 24180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load operand in rax into xmm1, or branch to not_numbers. 24280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfSmi(rax, &load_smi_rax); 24380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 24480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&load_nonsmi_rax); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(FieldOperand(rax, HeapObject::kMapOffset), rcx); 24680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, not_numbers); 24780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); 24880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&done); 24980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 25080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&load_smi_rdx); 25180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiToInteger32(kScratchRegister, rdx); 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtlsi2sd(xmm0, kScratchRegister); 25380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfNotSmi(rax, &load_nonsmi_rax); 25480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 25580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&load_smi_rax); 25680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiToInteger32(kScratchRegister, rax); 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtlsi2sd(xmm1, kScratchRegister); 25880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 25980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 26080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 26180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MathPowStub::Generate(MacroAssembler* masm) { 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register exponent = MathPowTaggedDescriptor::exponent(); 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(exponent.is(rdx)); 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Register base = rax; 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Register scratch = rcx; 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const XMMRegister double_result = xmm3; 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const XMMRegister double_base = xmm2; 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const XMMRegister double_exponent = xmm1; 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const XMMRegister double_scratch = xmm4; 271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label call_runtime, done, exponent_not_smi, int_exponent; 273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save 1 in double_result - we need this several times later on. 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, Immediate(1)); 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtlsi2sd(double_result, scratch); 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (exponent_type() == ON_STACK) { 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label base_is_smi, unpack_exponent; 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The exponent and base are supplied as arguments on the stack. 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This can only happen if the stub is called from non-optimized code. 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load input parameters from stack. 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(base, args.GetArgumentOperand(0)); 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(exponent, args.GetArgumentOperand(1)); 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(base, &base_is_smi, Label::kNear); 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset), 2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kHeapNumberMapRootIndex); 2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &call_runtime); 2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset)); 2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&unpack_exponent, Label::kNear); 2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&base_is_smi); 2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(base, base); 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtlsi2sd(double_base, base); 2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&unpack_exponent); 2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(exponent, exponent); 3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&int_exponent); 3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&exponent_not_smi); 3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(exponent, HeapObject::kMapOffset), 3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kHeapNumberMapRootIndex); 3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &call_runtime); 3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (exponent_type() == TAGGED) { 3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); 3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(exponent, exponent); 3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&int_exponent); 3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&exponent_not_smi); 3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (exponent_type() != INTEGER) { 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label fast_power, try_arithmetic_simplification; 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Detect integer exponents stored as double. 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ DoubleToI(exponent, double_exponent, double_scratch, 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification, 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &try_arithmetic_simplification, 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &try_arithmetic_simplification); 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&int_exponent); 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&try_arithmetic_simplification); 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cvttsd2si(exponent, double_exponent); 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Skip to runtime if possibly NaN (indicated by the indefinite integer). 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(exponent, Immediate(0x1)); 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(overflow, &call_runtime); 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (exponent_type() == ON_STACK) { 3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Detect square root case. Crankshaft detects constant +/-0.5 at 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compile time and uses DoMathPowHalf instead. We then skip this check 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for non-constant cases of +/-0.5 as these hardly occur. 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label continue_sqrt, continue_rsqrt, not_plus_half; 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test for 0.5. 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load double_scratch with 0.5. 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(scratch, V8_UINT64_C(0x3FE0000000000000)); 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(double_scratch, scratch); 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Already ruled out NaNs for exponent. 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ucomisd(double_scratch, double_exponent); 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, ¬_plus_half, Label::kNear); 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calculates square root of base. Check for the special case of 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // According to IEEE-754, double-precision -Infinity has the highest 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 12 bits set and the lowest 52 bits cleared. 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(scratch, V8_UINT64_C(0xFFF0000000000000)); 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(double_scratch, scratch); 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ucomisd(double_scratch, double_base); 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Comparing -Infinity with NaN results in "unordered", which sets the 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // zero flag as if both were equal. However, it also sets the carry flag. 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &continue_sqrt, Label::kNear); 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(carry, &continue_sqrt, Label::kNear); 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set result to Infinity in the special case. 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xorps(double_result, double_result); 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ subsd(double_result, double_scratch); 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&continue_sqrt); 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sqrtsd returns -0 when input is -0. ECMA spec requires +0. 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xorps(double_scratch, double_scratch); 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addsd(double_scratch, double_base); // Convert -0 to 0. 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sqrtsd(double_result, double_scratch); 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test for -0.5. 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_plus_half); 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load double_scratch with -0.5 by substracting 1. 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ subsd(double_scratch, double_result); 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Already ruled out NaNs for exponent. 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ucomisd(double_scratch, double_exponent); 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &fast_power, Label::kNear); 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calculates reciprocal of square root of base. Check for the special 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // case of Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // According to IEEE-754, double-precision -Infinity has the highest 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 12 bits set and the lowest 52 bits cleared. 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(scratch, V8_UINT64_C(0xFFF0000000000000)); 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(double_scratch, scratch); 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ucomisd(double_scratch, double_base); 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Comparing -Infinity with NaN results in "unordered", which sets the 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // zero flag as if both were equal. However, it also sets the carry flag. 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &continue_rsqrt, Label::kNear); 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(carry, &continue_rsqrt, Label::kNear); 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set result to 0 in the special case. 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xorps(double_result, double_result); 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&continue_rsqrt); 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sqrtsd returns -0 when input is -0. ECMA spec requires +0. 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xorps(double_exponent, double_exponent); 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addsd(double_exponent, double_base); // Convert -0 to +0. 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sqrtsd(double_exponent, double_exponent); 3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ divsd(double_result, double_exponent); 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 40185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Using FPU instructions to calculate power. 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fast_power_failed; 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_power); 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fnclex(); // Clear flags to catch exceptions later. 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Transfer (B)ase and (E)xponent onto the FPU register stack. 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rsp, Immediate(kDoubleSize)); 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(Operand(rsp, 0), double_exponent); 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fld_d(Operand(rsp, 0)); // E 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(Operand(rsp, 0), double_base); 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fld_d(Operand(rsp, 0)); // B, E 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Exponent is in st(1) and base is in st(0) 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // B ^ E = (2^(E * log2(B)) - 1) + 1 = (2^X - 1) + 1 for X = E * log2(B) 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FYL2X calculates st(1) * log2(st(0)) 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fyl2x(); // X 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fld(0); // X, X 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ frndint(); // rnd(X), X 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fsub(1); // rnd(X), X-rnd(X) 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fxch(1); // X - rnd(X), rnd(X) 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // F2XM1 calculates 2^st(0) - 1 for -1 < st(0) < 1 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ f2xm1(); // 2^(X-rnd(X)) - 1, rnd(X) 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fld1(); // 1, 2^(X-rnd(X)) - 1, rnd(X) 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ faddp(1); // 2^(X-rnd(X)), rnd(X) 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FSCALE calculates st(0) * 2^st(1) 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fscale(); // 2^X, rnd(X) 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fstp(1); 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Bail out to runtime in case of exceptions in the status word. 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fnstsw_ax(); 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(rax, Immediate(0x5F)); // Check for all but precision exception. 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_zero, &fast_power_failed, Label::kNear); 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fstp_d(Operand(rsp, 0)); 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(double_result, Operand(rsp, 0)); 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(kDoubleSize)); 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_power_failed); 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fninit(); 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(kDoubleSize)); 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&call_runtime); 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calculate power with integer exponent. 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&int_exponent); 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const XMMRegister double_scratch2 = double_exponent; 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Back up exponent as we need to check if exponent is negative later. 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, exponent); // Back up exponent. 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(double_scratch, double_base); // Back up base. 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(double_scratch2, double_result); // Load double_exponent with 1. 450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Get absolute value of exponent. 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_neg, while_true, while_false; 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testl(scratch, scratch); 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(positive, &no_neg, Label::kNear); 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ negl(scratch); 456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&no_neg); 457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &while_false, Label::kNear); 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ shrl(scratch, Immediate(1)); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Above condition means CF==0 && ZF==0. This means that the 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit that has been shifted out is 0 and the result is not 0. 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, &while_true, Label::kNear); 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movsd(double_result, double_scratch); 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &while_false, Label::kNear); 465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&while_true); 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shrl(scratch, Immediate(1)); 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mulsd(double_scratch, double_scratch); 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, &while_true, Label::kNear); 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mulsd(double_result, double_scratch); 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_zero, &while_true); 47285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&while_false); 4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the exponent is negative, return 1/result. 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testl(exponent, exponent); 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(greater, &done); 4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ divsd(double_scratch2, double_result); 4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(double_result, double_scratch2); 4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test whether result is zero. Bail out to check for subnormal result. 4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. 4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xorps(double_scratch2, double_scratch2); 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ucomisd(double_scratch2, double_result); 4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // double_exponent aliased as double_scratch2 has already been overwritten 4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and may not have contained the exponent value in the first place when the 4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // input was a smi. We reset it with exponent value before bailing out. 4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &done); 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtlsi2sd(double_exponent, exponent); 4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Returning or bailing out. 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = isolate()->counters(); 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (exponent_type() == ON_STACK) { 4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The arguments are still on the stack. 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&call_runtime); 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); 49585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The stub is called from non-optimized code, which expects the result 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // as heap number in rax. 4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateHeapNumber(rax, rcx, &call_runtime); 5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), double_result); 5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->math_pow(), 1); 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(2 * kPointerSize); 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&call_runtime); 5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Move base to the correct argument register. Exponent is already in xmm1. 5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(xmm0, double_base); 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(double_exponent.is(xmm1)); 5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(2); 5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction( 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::power_double_double_function(isolate()), 2); 5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Return value is in xmm0. 5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movsd(double_result, xmm0); 51685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->math_pow(), 1); 5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FunctionPrototypeStub::Generate(MacroAssembler* masm) { 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = LoadDescriptor::ReceiverRegister(); 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r9, &miss); 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&miss); 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyAccessCompiler::TailCallBuiltin( 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC)); 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 53680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 53780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The key is in rdx and the parameter count is in rax. 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rdx.is(ArgumentsAccessReadDescriptor::index())); 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rax.is(ArgumentsAccessReadDescriptor::parameter_count())); 54080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 54180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the key is a smi. 54280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow; 54380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfNotSmi(rdx, &slow); 54480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check if the calling frame is an arguments adaptor frame. We look at the 54644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // context offset, and if the frame is not a regular one, then we find a 54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Smi instead of the context. We can't use SmiCompare here, because that 54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // only works for comparing two smis. 54980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label adaptor; 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), 55244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 55380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, &adaptor); 55480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 55580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check index against formal parameters count limit passed in 55680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // through register rax. Use unsigned comparison to get negative 55780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // check for free. 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdx, rax); 55980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(above_equal, &slow); 56080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 56180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Read the argument from the stack and return it. 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiSub(rax, rax, rdx); 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rax, rax); 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rbp, rax, ARGUMENTS_DONT_CONTAIN_RECEIVER); 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, args.GetArgumentOperand(0)); 56680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Ret(); 56780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 56880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Arguments adaptor case: Check index against actual arguments 56980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // limit found in the arguments adaptor frame. Use unsigned 57080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // comparison to get negative check for free. 57180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&adaptor); 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdx, rcx); 57480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(above_equal, &slow); 57580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 57680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Read the argument from the stack and return it. 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiSub(rcx, rcx, rdx); 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rcx, rcx); 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor adaptor_args(rbx, rcx, 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ARGUMENTS_DONT_CONTAIN_RECEIVER); 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, adaptor_args.GetArgumentOperand(0)); 58280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Ret(); 58380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 58480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Slow-case: Handle non-smi or out-of-bounds access to arguments 58580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // by calling the runtime system. 58680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow); 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(rbx); 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushReturnAddressFrom(rbx); 59080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); 59180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 59280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 59380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { 5953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Stack layout: 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[0] : return address 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[8] : number of parameters (tagged) 5983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rsp[16] : receiver displacement 5993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rsp[24] : function 6003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Registers used over the whole function: 6013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rbx: the mapped parameter count (untagged) 6023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rax: the allocated object (tagged). 6033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate()->factory(); 6053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger64(rbx, args.GetArgumentOperand(2)); 6083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rbx = parameter count (untagged) 6093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if the calling frame is an arguments adaptor frame. 6113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label runtime; 6123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label adaptor_frame, try_allocate; 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 6153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 6163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(equal, &adaptor_frame); 6173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // No adaptor, parameter count = argument count. 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rbx); 6203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(&try_allocate, Label::kNear); 6213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We have an adaptor frame. Patch the parameters pointer. 6233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&adaptor_frame); 6243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger64(rcx, 6253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand(rdx, 6263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ArgumentsAdaptorFrameConstants::kLengthOffset)); 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rdx, Operand(rdx, rcx, times_pointer_size, 6283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch StandardFrameConstants::kCallerSPOffset)); 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(args.GetArgumentOperand(1), rdx); 6303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rbx = parameter count (untagged) 6323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rcx = argument count (untagged) 6333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compute the mapped parameter count = min(rbx, rcx) in rbx. 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rbx, rcx); 6353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(less_equal, &try_allocate, Label::kNear); 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, rcx); 6373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&try_allocate); 6393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compute the sizes of backing store, parameter map, and arguments object. 6413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 1. Parameter map, has 2 extra words containing context and backing store. 6423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int kParameterMapHeaderSize = 6433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedArray::kHeaderSize + 2 * kPointerSize; 6443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label no_parameter_map; 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xorp(r8, r8); 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rbx, rbx); 6473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(zero, &no_parameter_map, Label::kNear); 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize)); 6493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&no_parameter_map); 6503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 2. Backing store. 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(r8, Operand(r8, rcx, times_pointer_size, FixedArray::kHeaderSize)); 6533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // 3. Arguments object. 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(r8, Immediate(Heap::kSloppyArgumentsObjectSize)); 6563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Do the allocation of all three objects in one go. 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(r8, rax, rdx, rdi, &runtime, TAG_OBJECT); 6593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rax = address of new object(s) (tagged) 6613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rcx = argument count (untagged) 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the arguments map from the current native context into rdi. 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label has_mapped_parameters, instantiate; 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rbx, rbx); 6673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(not_zero, &has_mapped_parameters, Label::kNear); 6683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kIndex = Context::SLOPPY_ARGUMENTS_MAP_INDEX; 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rdi, Context::SlotOffset(kIndex))); 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&instantiate, Label::kNear); 6723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kAliasedIndex = Context::ALIASED_ARGUMENTS_MAP_INDEX; 6743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&has_mapped_parameters); 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex))); 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&instantiate); 6773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rax = address of new object (tagged) 6793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rbx = mapped parameter count (untagged) 6803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rcx = argument count (untagged) 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdi = address of arguments map (tagged) 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSObject::kMapOffset), rdi); 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); 6863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the callee in-object property. 6883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, args.GetArgumentOperand(0)); 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertNotSmi(rdx); 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSObject::kHeaderSize + 6923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Heap::kArgumentsCalleeIndex * kPointerSize), 6933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch rdx); 6943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Use the length (smi tagged) and set that as an in-object property too. 6963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Note: rcx is tagged from here on. 6973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 6983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Integer32ToSmi(rcx, rcx); 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSObject::kHeaderSize + 7003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Heap::kArgumentsLengthIndex * kPointerSize), 7013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch rcx); 7023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the elements pointer in the allocated arguments object. 7043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If we allocated a parameter map, edi will point there, otherwise to the 7053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // backing store. 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rdi, Operand(rax, Heap::kSloppyArgumentsObjectSize)); 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); 7083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rax = address of new object (tagged) 7103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rbx = mapped parameter count (untagged) 7113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rcx = argument count (tagged) 7123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rdi = address of parameter map or backing store (tagged) 7133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Initialize parameter map. If there are no mapped arguments, we're done. 7153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label skip_parameter_map; 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rbx, rbx); 7173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(zero, &skip_parameter_map); 7183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(kScratchRegister, Heap::kSloppyArgumentsElementsMapRootIndex); 7203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rbx contains the untagged argument count. Add 2 and tag to write. 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); 7223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Integer64PlusConstantToSmi(r9, rbx, 2); 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r9); 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi); 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9); 7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Copy the parameter slots and the holes in the arguments. 7293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We need to fill in mapped_parameter_count slots. They index the context, 7303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // where parameters are stored in reverse order, at 7313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 7323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // The mapped parameter thus need to get indices 7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // MIN_CONTEXT_SLOTS+parameter_count-1 .. 7343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count 7353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We loop from right to left. 7363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label parameters_loop, parameters_test; 7373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Load tagged parameter count into r9. 7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Integer32ToSmi(r9, rbx); 7403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS)); 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(r8, args.GetArgumentOperand(2)); 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(r8, r9); 7433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Move(r11, factory->the_hole_value()); 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, rdi); 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); 7463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r9 = loop variable (tagged) 7473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r8 = mapping index (tagged) 7483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // r11 = the hole value 7493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rdx = address of parameter map (tagged) 7503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rdi = address of backing store (tagged) 7513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(¶meters_test, Label::kNear); 7523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(¶meters_loop); 7543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiSubConstant(r9, r9, Smi::FromInt(1)); 7553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger64(kScratchRegister, r9); 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rdx, kScratchRegister, 7573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch times_pointer_size, 7583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch kParameterMapHeaderSize), 7593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch r8); 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rdi, kScratchRegister, 7613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch times_pointer_size, 7623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedArray::kHeaderSize), 7633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch r11); 7643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiAddConstant(r8, r8, Smi::FromInt(1)); 7653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(¶meters_test); 7663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiTest(r9); 7673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(not_zero, ¶meters_loop, Label::kNear); 7683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&skip_parameter_map); 7703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rcx = argument count (tagged) 7723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rdi = address of backing store (tagged) 7733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Copy arguments header and remaining slots (if there are any). 7743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Move(FieldOperand(rdi, FixedArray::kMapOffset), 7753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch factory->fixed_array_map()); 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); 7773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label arguments_loop, arguments_test; 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(r8, rbx); 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, args.GetArgumentOperand(1)); 7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Untag rcx for the loop below. 7823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger64(rcx, rcx); 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(kScratchRegister, Operand(r8, times_pointer_size, 0)); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rdx, kScratchRegister); 7853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(&arguments_test, Label::kNear); 7863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&arguments_loop); 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rdx, Immediate(kPointerSize)); 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(r9, Operand(rdx, 0)); 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rdi, r8, 7913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch times_pointer_size, 7923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedArray::kHeaderSize), 7933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch r9); 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(r8, Immediate(1)); 7953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&arguments_test); 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(r8, rcx); 7983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(less, &arguments_loop, Label::kNear); 7993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Return and remove the on-stack parameters. 8013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(3 * kPointerSize); 8023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Do the runtime call to allocate the arguments object. 8043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rcx = argument count (untagged) 8053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&runtime); 8063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Integer32ToSmi(rcx, rcx); 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(args.GetArgumentOperand(2), rcx); // Patch argument count. 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); 8093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 8103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[0] : return address 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[8] : number of parameters 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[16] : receiver displacement 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[24] : function 8173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if the calling frame is an arguments adaptor frame. 8193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label runtime; 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 8223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 8233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(not_equal, &runtime); 8243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Patch the arguments.length and the parameters pointer. 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(args.GetArgumentOperand(2), rcx); 8293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger64(rcx, rcx); 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rdx, Operand(rdx, rcx, times_pointer_size, 8313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch StandardFrameConstants::kCallerSPOffset)); 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(args.GetArgumentOperand(1), rdx); 8333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&runtime); 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return address is on the stack. 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow; 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = LoadDescriptor::ReceiverRegister(); 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key = LoadDescriptor::NameRegister(); 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = rax; 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch.is(receiver) && !scratch.is(key)); 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the key is an array index, that is Uint32. 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiValueSize <= 32); 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpUnlessNonNegativeSmi(key, &slow); 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Everything is fine, call runtime. 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(scratch); 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver); // receiver 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(key); // key 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushReturnAddressFrom(scratch); 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform tail call to the entry. 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference( 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(IC::kLoadElementWithInterceptor), 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()), 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2, 1); 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyAccessCompiler::TailCallBuiltin( 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); 8673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 8683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[0] : return address 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[8] : number of parameters 87380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rsp[16] : receiver displacement 87480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rsp[24] : function 87580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 87680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check if the calling frame is an arguments adaptor frame. 87780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label adaptor_frame, try_allocate, runtime; 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 8803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 88180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, &adaptor_frame); 88280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 88380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Get the length from the frame. 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, args.GetArgumentOperand(2)); 8863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger64(rcx, rcx); 88780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&try_allocate); 88880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 88980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Patch the arguments.length and the parameters pointer. 89080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&adaptor_frame); 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(args.GetArgumentOperand(2), rcx); 8933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger64(rcx, rcx); 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rdx, Operand(rdx, rcx, times_pointer_size, 8953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch StandardFrameConstants::kCallerSPOffset)); 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(args.GetArgumentOperand(1), rdx); 89780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 89880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Try the new space allocation. Start out with computing the size of 89980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // the arguments object and the elements array. 90080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label add_arguments_object; 90180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&try_allocate); 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rcx, rcx); 9033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(zero, &add_arguments_object, Label::kNear); 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize)); 90580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&add_arguments_object); 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rcx, Immediate(Heap::kStrictArgumentsObjectSize)); 90780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 90880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Do the allocation of both objects in one go. 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the arguments map from the current native context. 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int offset = Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX); 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rdi, offset)); 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSObject::kMapOffset), rdi); 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); 92180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 92280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Get the length (smi tagged) and set that as an in-object property too. 9233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, args.GetArgumentOperand(2)); 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSObject::kHeaderSize + 9263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Heap::kArgumentsLengthIndex * kPointerSize), 92744f0eee88ff00398ff7f715fab053374d808c90dSteve Block rcx); 92880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 92980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If there are no actual arguments, we're done. 93080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label done; 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rcx, rcx); 93280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, &done); 93380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 9343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the parameters pointer from the stack. 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, args.GetArgumentOperand(1)); 93680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the elements pointer in the allocated arguments object and 93880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // initialize the header in the elements fixed array. 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rdi, Operand(rax, Heap::kStrictArgumentsObjectSize)); 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); 94180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); 9433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); 9463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Untag the length for the loop below. 9473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger64(rcx, rcx); 94880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 94980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Copy the fixed array slots. 95080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label loop; 95180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&loop); 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, Operand(rdx, -1 * kPointerSize)); // Skip receiver. 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rdi, FixedArray::kHeaderSize), rbx); 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rdi, Immediate(kPointerSize)); 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rdx, Immediate(kPointerSize)); 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ decp(rcx); 95780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, &loop); 95880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 95980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return and remove the on-stack parameters. 96080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 96180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ret(3 * kPointerSize); 96280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 96380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Do the runtime call to allocate the arguments object. 96480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&runtime); 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1); 96680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 96780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 96880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 96980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid RegExpExecStub::Generate(MacroAssembler* masm) { 97080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Just jump directly to runtime if native RegExp is not selected at compile 97180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // time or if regexp entry in generated code is turned off runtime switch or 97280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // at compilation. 97380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef V8_INTERPRETED_REGEXP 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1); 97580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#else // V8_INTERPRETED_REGEXP 97680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 97780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Stack frame on entry. 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[0] : return address 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[8] : last_match_info (expected JSArray) 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[16] : previous index 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[24] : subject string 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[32] : JSRegExp object 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum RegExpExecStubArgumentIndices { 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JS_REG_EXP_OBJECT_ARGUMENT_INDEX, 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SUBJECT_STRING_ARGUMENT_INDEX, 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PREVIOUS_INDEX_ARGUMENT_INDEX, 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LAST_MATCH_INFO_ARGUMENT_INDEX, 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch REG_EXP_EXEC_ARGUMENT_COUNT 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, REG_EXP_EXEC_ARGUMENT_COUNT, 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ARGUMENTS_DONT_CONTAIN_RECEIVER); 99480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label runtime; 99580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Ensure that a RegExp stack is allocated. 99680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ExternalReference address_of_regexp_stack_memory_address = 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_regexp_stack_memory_address(isolate()); 99880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ExternalReference address_of_regexp_stack_memory_size = 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_regexp_stack_memory_size(isolate()); 100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Load(kScratchRegister, address_of_regexp_stack_memory_size); 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(kScratchRegister, kScratchRegister); 100280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, &runtime); 100380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 100480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the first argument is a JSRegExp object. 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX)); 100680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfSmi(rax, &runtime); 100780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); 100880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, &runtime); 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 101080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the RegExp has been compiled (data contains a fixed array). 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, JSRegExp::kDataOffset)); 101280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (FLAG_debug_code) { 101344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Condition is_smi = masm->CheckSmi(rax); 101480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Check(NegateCondition(is_smi), 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kUnexpectedTypeForRegExpDataFixedArrayExpected); 101644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister); 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected); 101880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 101980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 102044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rax: RegExp data (FixedArray) 102180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 102244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(rbx, FieldOperand(rax, JSRegExp::kDataTagOffset)); 102380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP)); 102480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, &runtime); 102580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 102644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rax: RegExp data (FixedArray) 102780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the number of captures fit in the static offsets vector buffer. 102880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiToInteger32(rdx, 102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset)); 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check (number_of_captures + 1) * 2 <= offsets vector size 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Or number_of_captures <= offsets vector size / 2 - 1 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); 103480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(above, &runtime); 103580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 103669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Reset offset for possibly sliced string. 103769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Set(r14, 0); 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(rdi, &runtime); 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(r15, rdi); // Make a copy of the original subject string. 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 104280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rax: RegExp data (FixedArray) 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdi: subject string 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r15: subject string 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle subject string according to its encoding and representation: 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (1) Sequential two byte? If yes, go to (9). 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (2) Sequential one byte? If yes, go to (6). 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (3) Anything but sequential or cons? If yes, go to (7). 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (4) Cons string. If the string is flat, replace subject with first string. 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Otherwise bailout. 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (5a) Is subject sequential two byte? If yes, go to (9). 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (5b) Is subject external? If yes, go to (8). 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (6) One byte sequential. Load regexp code for one byte. 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (E) Carry on. 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch /// [...] 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Deferred code at the end of the stub: 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (7) Not a long external string? If yes, go to (10). 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (8) External string. Make it, offset-wise, look like a sequential string. 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (8a) Is the external string one byte? If yes, go to (6). 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (9) Two byte sequential. Load regexp code for one byte. Go to (E). 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (10) Short external string or not a string? If yes, bail out to runtime. 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (11) Sliced string. Replace subject with parent. Go to (5a). 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */, 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch external_string /* 8 */, check_underlying /* 5a */, 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch not_seq_nor_cons /* 7 */, check_code /* E */, 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch not_long_external /* 10 */; 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (1) Sequential two byte? If yes, go to (9). 10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ andb(rbx, Immediate(kIsNotStringMask | 10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kStringRepresentationMask | 10743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kStringEncodingMask | 10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kShortExternalStringMask)); 107680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &seq_two_byte_string); // Go to (9). 1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (2) Sequential one byte? If yes, go to (6). 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Any other sequential string must be one byte. 10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ andb(rbx, Immediate(kIsNotStringMask | 10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kStringRepresentationMask | 10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kShortExternalStringMask)); 1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6). 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (3) Anything but sequential or cons? If yes, go to (7). 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We check whether the subject string is a cons, since sequential strings 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // have already been covered. 108969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kConsStringTag < kExternalStringTag); 109069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rbx, Immediate(kExternalStringTag)); 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(greater_equal, ¬_seq_nor_cons); // Go to (7). 109569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (4) Cons string. Check that it's flat. 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace subject with first string and reload instance type. 109844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kempty_stringRootIndex); 110080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, &runtime); 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); 1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_underlying); 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 110580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (5a) Is subject sequential two byte? If yes, go to (9). 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask)); 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &seq_two_byte_string); // Go to (9). 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (5b) Is subject external? If yes, go to (8). 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testb(rbx, Immediate(kStringRepresentationMask)); 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The underlying external string is never a short external string. 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); 1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); 1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &external_string); // Go to (8) 1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (6) One byte sequential. Load regexp code for one byte. 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&seq_one_byte_string); 1119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // rax: RegExp data (FixedArray) 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset)); 1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(rcx, 1); // Type is one byte. 112280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (E) Carry on. String handling is done. 112480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&check_code); 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r11: irregexp code 112680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the irregexp code has been generated for the actual string 112780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // encoding. If it has, the field contains a code object otherwise it contains 1128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // smi (code flushing support) 1129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(r11, &runtime); 113080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdi: sequential subject string (or look-alike, external string) 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r15: original subject string 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rcx: encoding of subject string (1 if one_byte, 0 if two_byte); 113480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // r11: code 113580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load used arguments before starting to push arguments for call to native 113680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // RegExp code to avoid handling changing stack height. 1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to use r15 instead of rdi to load the length because rdi might 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // have been only made to look like a sequential string when it actually 1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is an external string. 1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, args.GetArgumentOperand(PREVIOUS_INDEX_ARGUMENT_INDEX)); 1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(rbx, &runtime); 1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset)); 1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above_equal, &runtime); 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger64(rbx, rbx); 114580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // rdi: subject string 114780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rbx: previous index 1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rcx: encoding of subject string (1 if one_byte 0 if two_byte); 114980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // r11: code 115080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // All checks done. Now push arguments for native regexp code. 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = isolate()->counters(); 115244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->regexp_entry_native(), 1); 115380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 115444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Isolates: note we add an additional parameter here (isolate pointer). 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kRegExpExecuteArguments = 9; 115680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen int argument_slots_on_stack = 115780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); 115844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ EnterApiExitFrame(argument_slots_on_stack); 115980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument 9: Pass current isolate address. 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadAddress(kScratchRegister, 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::isolate_address(isolate())); 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kRegisterSize), 116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block kScratchRegister); 116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument 8: Indicate that this is a direct call from JavaScript. 1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kRegisterSize), 116880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1)); 116980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument 7: Start (high end) of backtracking stack memory area. 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(kScratchRegister, address_of_regexp_stack_memory_address); 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(r9, Operand(kScratchRegister, 0)); 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(kScratchRegister, address_of_regexp_stack_memory_size); 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(r9, Operand(kScratchRegister, 0)); 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kRegisterSize), r9); 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument 6: Set the number of capture registers to zero to force global 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // regexps to behave as non-global. This does not affect non-global regexps. 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument 6 is passed in r9 on Linux and on the stack on Windows. 118080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kRegisterSize), 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(0)); 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(r9, 0); 118580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif 118680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 118780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Argument 5: static offsets vector buffer. 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadAddress( 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r8, ExternalReference::address_of_static_offsets_vector(isolate())); 119080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Argument 5 passed in r8 on Linux and on the stack on Windows. 119180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64 1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(Operand(rsp, (argument_slots_on_stack - 5) * kRegisterSize), r8); 119380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif 119480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // rdi: subject string 119680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rbx: previous index 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rcx: encoding of subject string (1 if one_byte 0 if two_byte); 119880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // r11: code 119969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // r14: slice offset 120069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // r15: original subject string 120169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 120269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Argument 2: Previous index. 1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(arg_reg_2, rbx); 120480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 120580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Argument 4: End of string data 120680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Argument 3: Start of string data 120769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label setup_two_byte, setup_rest, got_length, length_not_from_slice; 120869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Prepare start and end index of the input. 120969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Load the length from the original sliced string if that is the case. 1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rbx, r14); 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(arg_reg_3, FieldOperand(r15, String::kLengthOffset)); 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(r14, arg_reg_3); // Using arg3 as scratch. 121369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 121469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // rbx: start index of the input 121569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // r14: end index of the input 121669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // r15: original subject string 1217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. 1218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &setup_two_byte, Label::kNear); 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(arg_reg_4, 1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(rdi, r14, times_1, SeqOneByteString::kHeaderSize)); 1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(arg_reg_3, 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(rdi, rbx, times_1, SeqOneByteString::kHeaderSize)); 1223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&setup_rest, Label::kNear); 122480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&setup_two_byte); 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(arg_reg_4, 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize)); 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(arg_reg_3, 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); 122980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&setup_rest); 123080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 123169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Argument 1: Original subject string. 123269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // The original subject is in the previous stack frame. Therefore we have to 123369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // use rbp, which points exactly to one pointer size below the previous rsp. 123469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // (Because creating a new stack frame pushes the previous rbp onto the stack 123569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // and thereby moves up rsp by one kPointerSize.) 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(arg_reg_1, r15); 123780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 123880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Locate the code entry and call it. 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); 1240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ call(r11); 124180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LeaveApiExitFrame(true); 124380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 124480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check the result. 1245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label success; 1246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label exception; 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rax, Immediate(1)); 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We expect exactly one result since we force the called regexp to behave 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // as non-global. 1250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &success, Label::kNear); 125180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); 1252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(equal, &exception); 1253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); 1254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If none of the above, it can only be retry. 1255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Handle that in the runtime system. 125680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, &runtime); 1257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // For failure return null. 1259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(rax, Heap::kNullValueRootIndex); 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize); 126180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 126280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load RegExp data. 126380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&success); 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX)); 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); 126680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiToInteger32(rax, 126780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); 126880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Calculate number of capture registers (number_of_captures + 1) * 2. 126980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ leal(rdx, Operand(rax, rax, times_1, 2)); 127080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 127180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rdx: Number of capture registers 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the fourth object is a JSArray object. 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(r15, args.GetArgumentOperand(LAST_MATCH_INFO_ARGUMENT_INDEX)); 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(r15, &runtime); 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(r15, JS_ARRAY_TYPE, kScratchRegister); 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &runtime); 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the JSArray is in fast case. 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(r15, JSArray::kElementsOffset)); 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rbx, HeapObject::kMapOffset)); 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex); 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &runtime); 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the last match info has space for the capture registers and the 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // additional information. Ensure no overflow in add. 1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subl(rax, Immediate(RegExpImpl::kLastMatchOverhead)); 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rdx, rax); 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(greater, &runtime); 128980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 129080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rbx: last_match_info backing store (FixedArray) 129180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rdx: number of capture registers 129280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Store the capture count. 129380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Integer32ToSmi(kScratchRegister, rdx); 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), 129580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen kScratchRegister); 129680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Store last subject and last input. 1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); 1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rax); 13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rbx, 13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RegExpImpl::kLastSubjectOffset, 13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, 13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rdi, 13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, rcx); 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); 13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rbx, 13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RegExpImpl::kLastInputOffset, 13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, 13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rdi, 13113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 131280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 131380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Get the static offsets vector filled by the native regexp code. 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadAddress( 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rcx, ExternalReference::address_of_static_offsets_vector(isolate())); 131680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 131780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rbx: last_match_info backing store (FixedArray) 131880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rcx: offsets vector 131980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rdx: number of capture registers 1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label next_capture, done; 132180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Capture register counter starts from number of capture registers and 132280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // counts down until wraping after zero. 132380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&next_capture); 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rdx, Immediate(1)); 1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(negative, &done, Label::kNear); 132680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Read the value from the static offsets vector buffer and make it a smi. 132780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movl(rdi, Operand(rcx, rdx, times_int_size, 0)); 13280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Integer32ToSmi(rdi, rdi); 132980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Store the smi value in the last match info. 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rbx, 133180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen rdx, 133280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen times_pointer_size, 133380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen RegExpImpl::kFirstCaptureOffset), 133480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen rdi); 133580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&next_capture); 133680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 133780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 133880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return last match info. 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, r15); 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize); 134180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&exception); 1343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result must now be exception. If there is no pending exception already a 1344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // stack overflow (on the backtrack stack) was detected in RegExp code but 1345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // haven't created the exception yet. Handle that in the runtime system. 1346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(592): Rerunning the RegExp to get the stack overflow exception. 134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference pending_exception_address( 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate::kPendingExceptionAddress, isolate()); 134944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand pending_exception_operand = 135044f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->ExternalOperand(pending_exception_address, rbx); 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, pending_exception_operand); 1352e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rax, rdx); 1354e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(equal, &runtime); 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(pending_exception_operand, rdx); 1356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1357e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); 1358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label termination_exception; 1359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &termination_exception, Label::kNear); 1360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Throw(rax); 1361e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1362e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&termination_exception); 13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ThrowUncatchable(rax); 13643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do the runtime call to execute the regexp. 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&runtime); 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1); 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Deferred code for string handling. 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (7) Not a long external string? If yes, go to (10). 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_seq_nor_cons); 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compare flags are still set from (3). 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(greater, ¬_long_external, Label::kNear); // Go to (10). 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (8) External string. Short external strings have been ruled out. 13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&external_string); 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert that we do not have a cons or slice (indirect strings) here. 13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sequential strings have already been ruled out. 13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(rbx, Immediate(kIsIndirectStringMask)); 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(zero, kExternalStringExpectedButNotFound); 13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); 13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Move the pointer so that offset-wise, it looks like a sequential string. 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kTwoByteStringTag == 0); 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (8a) Is the external string one byte? If yes, go to (6). 13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(rbx, Immediate(kStringEncodingMask)); 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &seq_one_byte_string); // Goto (6). 1393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdi: subject string (flat two-byte) 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rax: RegExp data (FixedArray) 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (9) Two byte sequential. Load regexp code for one byte. Go to (E). 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&seq_two_byte_string); 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(rcx, 0); // Type is two byte. 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&check_code); // Go to (E). 1401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (10) Not a string or a short external string? If yes, bail out to runtime. 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_long_external); 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Catch non-string subject or short external string. 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &runtime); 140880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (11) Sliced string. Replace subject with parent. Go to (5a). 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load offset into r14 and replace subject string with parent. 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&check_underlying); 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_INTERPRETED_REGEXP 141580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 141680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 141780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int NegativeComparisonResult(Condition cc) { 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cc != equal); 1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((cc == less) || (cc == less_equal) 1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch || (cc == greater) || (cc == greater_equal)); 1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (cc == greater || cc == greater_equal) ? LESS : GREATER; 142380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 142480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 142580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckInputType(MacroAssembler* masm, Register input, 1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompareICState::State expected, Label* fail) { 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected == CompareICState::SMI) { 1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(input, fail); 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (expected == CompareICState::NUMBER) { 1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, &ok); 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareMap(input, masm->isolate()->factory()->heap_number_map()); 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, fail); 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We could be strict about internalized/non-internalized here, but as long as 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // hydrogen doesn't care, the stub doesn't have to care either. 1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 143980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 144080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 144180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void BranchIfNotInternalizedString(MacroAssembler* masm, 1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* label, 1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch) { 1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(object, label); 1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, FieldOperand(object, HeapObject::kMapOffset)); 1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbp(scratch, 1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(scratch, Map::kInstanceTypeOffset)); 1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testb(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); 1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, label); 145380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 145480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 145580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateGeneric(MacroAssembler* masm) { 145780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label check_unequal_objects, done; 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cc = GetCondition(); 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate()->factory(); 14600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckInputType(masm, rdx, left(), &miss); 1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckInputType(masm, rax, right(), &miss); 1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compare two smis. 1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label non_smi, smi_done; 1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotBothSmi(rax, rdx, &non_smi); 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rdx, rax); 1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(no_overflow, &smi_done); 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ notp(rdx); // Correct sign in case of overflow. rdx cannot be 0 here. 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&smi_done); 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, rdx); 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&non_smi); 14750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 147680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The compare stub returns a positive, negative, or zero 64-bit integer 147780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // value in rax, corresponding to result of comparing the two inputs. 147880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // NOTICE! This code is only reached after a smi-fast-case check, so 147980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // it is certain that at least one operand isn't a smi. 148080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 148180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Two identical objects are equal unless they are both NaN or undefined. 148280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen { 1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_identical; 1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rax, rdx); 1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, ¬_identical, Label::kNear); 148680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc != equal) { 148880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undefined. undefined OP undefined is false even though 148980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // undefined == undefined. 1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label check_for_nan; 149180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); 1492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &check_for_nan, Label::kNear); 1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(rax, NegativeComparisonResult(cc)); 149480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ret(0); 149580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&check_for_nan); 149680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 149780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), 149980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // so we do the second best thing - test it ourselves. 1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label heap_number; 1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If it's not a heap number, then return equal for (in)equality operator. 1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory->heap_number_map()); 1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &heap_number, Label::kNear); 1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc != equal) { 1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call runtime on identical objects. Otherwise return equal. 1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); 1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above_equal, ¬_identical, Label::kNear); 1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(rax, EQUAL); 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 151280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&heap_number); 1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It is a heap number, so return equal if it's not NaN. 1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For NaN, return 1 for every condition except greater and 1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // greater-equal. Return -1 for them, so the comparison yields 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // false for all conditions except not-equal. 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(rax, EQUAL); 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); 1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ucomisd(xmm0, xmm0); 1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ setcc(parity_even, rax); 1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rax is 0 for equal non-NaN heapnumbers, 1 for NaNs. 1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc == greater_equal || cc == greater) { 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ negp(rax); 152580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 152780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 152880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(¬_identical); 152980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 153080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc == equal) { // Both strict and non-strict. 153280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow; // Fallthrough label. 153380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 153480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If we're doing a strict equality comparison, we don't have to do 153580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // type conversion, so we generate code to do fast comparison for objects 153680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // and oddballs. Non-smi numbers and strings still go through the usual 153780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // slow-case code. 1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (strict()) { 153980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If either is a Smi (we know that not both are), then they can only 154080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // be equal if the other is a HeapNumber. If so, use the slow case. 154180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen { 154280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label not_smis; 154380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SelectNonSmi(rbx, rax, rdx, ¬_smis); 154480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 154580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check if the non-smi operand is a heap number. 154680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), 1547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch factory->heap_number_map()); 154880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If heap number, handle it in the slow case. 154980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, &slow); 155080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return non-equal. ebx (the lower half of rbx) is not zero. 1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, rbx); 155280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ret(0); 155380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 155480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(¬_smis); 155580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 155680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 155780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If either operand is a JSObject or an oddball value, then they are not 155880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // equal since their pointers are different 155980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // There is no test for undetectability in strict equality. 156080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 156180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If the first object is a JS object, we have done pointer comparison. 15623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); 1563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label first_non_object; 15643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); 1565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(below, &first_non_object, Label::kNear); 1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return non-zero (rax (not rax) is not zero) 156780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label return_not_equal; 156880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen STATIC_ASSERT(kHeapObjectTag != 0); 156980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&return_not_equal); 157080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ret(0); 157180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 157280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&first_non_object); 157380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for oddballs: true, false, null, undefined. 157480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpInstanceType(rcx, ODDBALL_TYPE); 157580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, &return_not_equal); 157680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 15773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rdx, FIRST_SPEC_OBJECT_TYPE, rcx); 157880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(above_equal, &return_not_equal); 157980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 158080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for oddballs: true, false, null, undefined. 158180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpInstanceType(rcx, ODDBALL_TYPE); 158280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, &return_not_equal); 158380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 158480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Fall through to the general case. 158580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 158680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow); 158780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 158880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 158980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Generate the number comparison code. 1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label non_number_comparison; 1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label unordered; 1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison); 1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xorl(rax, rax); 1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xorl(rcx, rcx); 1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ucomisd(xmm0, xmm1); 159680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't base result on EFLAGS when a NaN is involved. 1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(parity_even, &unordered, Label::kNear); 1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return a result of -1, 0, or 1, based on EFLAGS. 1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ setcc(above, rax); 1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ setcc(below, rcx); 1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rax, rcx); 1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 160480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If one of the numbers was NaN, then the result is always false. 1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The cc is never not-equal. 1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&unordered); 1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cc != not_equal); 1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc == less || cc == less_equal) { 1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(rax, 1); 1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(rax, -1); 161380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 161580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The number comparison code did not provide a valid result. 1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&non_number_comparison); 161880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fast negative check for internalized-to-internalized equality. 1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label check_for_strings; 1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc == equal) { 1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BranchIfNotInternalizedString( 1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, &check_for_strings, rax, kScratchRegister); 1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BranchIfNotInternalizedString( 1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, &check_for_strings, rdx, kScratchRegister); 1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We've already checked for object identity, so if both operands are 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // internalized strings they aren't equal. Register rax (not rax) already 1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // holds a non-zero value, which indicates not equal, so just return. 163080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ret(0); 163180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 163280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 163380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&check_for_strings); 163480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotBothSequentialOneByteStrings(rdx, rax, rcx, rbx, 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &check_unequal_objects); 163780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Inline comparison of one-byte strings. 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc == equal) { 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringHelper::GenerateFlatOneByteStringEquals(masm, rdx, rax, rcx, rbx); 1641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringHelper::GenerateCompareFlatOneByteStrings(masm, rdx, rax, rcx, rbx, 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rdi, r8); 1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 164580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 164680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef DEBUG 1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kUnexpectedFallThroughFromStringComparison); 164880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif 164980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 165080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&check_unequal_objects); 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc == equal && !strict()) { 165280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Not strict equality. Objects are unequal if 165380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // they are both JSObjects and not undetectable, 165480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // and their pointers are different. 1655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_both_objects, return_unequal; 165680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // At most one is a smi, so we can test for smi by adding the two. 165780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // A smi plus a heap object has the low bit set, a heap object plus 165880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // a heap object has the low bit clear. 165980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen STATIC_ASSERT(kSmiTag == 0); 166080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen STATIC_ASSERT(kSmiTagMask == 1); 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rcx, Operand(rax, rdx, times_1, 0)); 166280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(rcx, Immediate(kSmiTagMask)); 1663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, ¬_both_objects, Label::kNear); 16643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx); 1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(below, ¬_both_objects, Label::kNear); 16663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rdx, FIRST_SPEC_OBJECT_TYPE, rcx); 1667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(below, ¬_both_objects, Label::kNear); 166880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 166980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1 << Map::kIsUndetectable)); 1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &return_unequal, Label::kNear); 167180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rcx, Map::kBitFieldOffset), 167280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1 << Map::kIsUndetectable)); 1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &return_unequal, Label::kNear); 167480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The objects are both undetectable, so they both compare as the value 167580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // undefined, and are equal. 167680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Set(rax, EQUAL); 167780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&return_unequal); 16781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Return non-equal by returning the non-zero object pointer in rax, 167980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // or return equal if we fell through to here. 168080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ret(0); 168180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(¬_both_objects); 168280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 168380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 168480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Push arguments below the return address to prepare jump to builtin. 1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(rcx); 1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 168880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 168980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Figure out which native to call and setup the arguments. 169080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Builtins::JavaScript builtin; 1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc == equal) { 1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch builtin = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; 169380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 169480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen builtin = Builtins::COMPARE; 1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(NegativeComparisonResult(cc))); 169680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 169780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushReturnAddressFrom(rcx); 169980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 170080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 170180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // tagged as a small integer. 170280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ InvokeBuiltin(builtin, JUMP_FUNCTION); 170380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&miss); 1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMiss(masm); 17063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 17073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateRecordCallTarget(MacroAssembler* masm) { 1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Cache the called function in a feedback vector slot. Cache states 17113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // are uninitialized, monomorphic (indicated by a JSFunction), and 17123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // megamorphic. 1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rax : number of arguments to the construct function 1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rbx : Feedback vector 1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdx : slot in feedback vector (Smi) 17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi : the function to call 17173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Isolate* isolate = masm->isolate(); 1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label initialize, done, miss, megamorphic, not_array_function, 1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch done_no_smi_convert; 17203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the cache state into rcx. 1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rdx, rdx); 1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, 1724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::kHeaderSize)); 17253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A monomorphic cache hit or an already megamorphic state: invoke the 17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // function without changing the state. 1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rcx, rdi); 1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &done); 1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate)); 1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &done); 1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!FLAG_pretenuring_call_new) { 1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we came here, we need to see if we are the array function. 1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we didn't have a matching function, and we didn't find the megamorph 1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sentinel, then we have in the slot either some other function or an 1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // AllocationSite. Do a map check on the object in rcx. 1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> allocation_site_map = 1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->factory()->allocation_site_map(); 1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(FieldOperand(rcx, 0), allocation_site_map); 1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &miss); 1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure the function is the Array() function 1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx); 1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdi, rcx); 1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &megamorphic); 1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&miss); 17513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A monomorphic miss (i.e, here the cache is not uninitialized) goes 17533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // megamorphic. 1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(rcx, TypeFeedbackVector::UninitializedSentinel(isolate)); 1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &initialize); 17563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MegamorphicSentinel is an immortal immovable object (undefined) so no 17573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // write-barrier is needed. 1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&megamorphic); 1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), 1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackVector::MegamorphicSentinel(isolate)); 1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 17623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // An uninitialized cache is patched with the function or sentinel to 1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // indicate the ElementsKind if function is the Array constructor. 17653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&initialize); 17663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!FLAG_pretenuring_call_new) { 1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure the function is the Array() function 1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx); 1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdi, rcx); 1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, ¬_array_function); 17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Arguments register must be smi-tagged to call out. 1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Integer32ToSmi(rax, rax); 1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdi); 1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Integer32ToSmi(rdx, rdx); 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rbx); 1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateAllocationSiteStub create_stub(isolate); 1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&create_stub); 1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rbx); 1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdx); 1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdi); 1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rax); 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rax, rax); 1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done_no_smi_convert); 1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_array_function); 179680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 179780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), 1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rdi); 180080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We won't need rdx or rbx anymore, just save rdi 1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdi); 1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rbx); 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteArray(rbx, rdi, rdx, kDontSaveFPRegs, 1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdx); 1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rbx); 1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdi); 1810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Integer32ToSmi(rdx, rdx); 181380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done_no_smi_convert); 1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { 1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do not transform the receiver for strict mode functions. 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); 1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testb(FieldOperand(rcx, SharedFunctionInfo::kStrictModeByteOffset), 1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); 1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, cont); 1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do not transform the receiver for natives. 1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // SharedFunctionInfo is already loaded into rcx. 1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testb(FieldOperand(rcx, SharedFunctionInfo::kNativeByteOffset), 1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); 1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, cont); 1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EmitSlowCase(Isolate* isolate, 1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, 1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor* args, 1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int argc, 1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* non_function) { 1838589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Check for function proxy. 1839589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); 1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, non_function); 1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(rcx); 1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdi); // put proxy as additional argument under return address 1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushReturnAddressFrom(rcx); 1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(rax, argc + 1); 1845589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Set(rbx, 0); 1846589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); 1847589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch { 1848589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Handle<Code> adaptor = 1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); 1850589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ jmp(adaptor, RelocInfo::CODE_TARGET); 1851589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1852589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the original receiver from the call site). 1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(non_function); 1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(args->GetReceiverOperand(), rdi); 1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(rax, argc); 1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(rbx, 0); 1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); 1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> adaptor = 1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->builtins()->ArgumentsAdaptorTrampoline(); 1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Jump(adaptor, RelocInfo::CODE_TARGET); 1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EmitWrapCase(MacroAssembler* masm, 1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor* args, 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* cont) { 1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Wrap the receiver and patch it back onto the stack. 1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { FrameScope frame_scope(masm, StackFrame::INTERNAL); 1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdi); 1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdi); 1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(args->GetReceiverOperand(), rax); 1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(cont); 1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CallFunctionNoFeedback(MacroAssembler* masm, 1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int argc, bool needs_checks, 1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool call_as_method) { 1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdi : the function to call 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // wrap_and_call can only be true if we are compiling a monomorphic method. 1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow, non_function, wrap, cont; 1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, argc); 1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (needs_checks) { 1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the function really is a JavaScript function. 1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(rdi, &non_function); 1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Goto slow case if we do not have a function. 1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &slow); 1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fast-case: Just invoke the function. 1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount actual(argc); 1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (call_as_method) { 1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (needs_checks) { 1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitContinueIfStrictOrNative(masm, &cont); 1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the receiver from the stack. 1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, args.GetReceiverOperand()); 1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (needs_checks) { 1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(rax, &wrap); 1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); 1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, &wrap); 1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&wrap); 1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&cont); 1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); 1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (needs_checks) { 1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Slow-case: Non-function called. 1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitSlowCase(isolate, masm, &args, argc, &non_function); 1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (call_as_method) { 1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&wrap); 1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitWrapCase(masm, &args, &cont); 1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallFunctionStub::Generate(MacroAssembler* masm) { 1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); 194080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 194180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 194280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 19433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallConstructStub::Generate(MacroAssembler* masm) { 19443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax : number of arguments 1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rbx : feedback vector 1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdx : (only if rbx is not the megamorphic symbol) slot in feedback 1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // vector (Smi) 19483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi : constructor function 19493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label slow, non_function_call; 19503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that function is not a smi. 19523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rdi, &non_function_call); 19533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that function is a JSFunction. 19543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 19553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &slow); 19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (RecordCallTarget()) { 19583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateRecordCallTarget(masm); 1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rdx, rdx); 1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_pretenuring_call_new) { 1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put the AllocationSite from the feedback vector into ebx. 1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // By adding kPointerSize we encode that we know the AllocationSite 1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // entry is at the feedback vector slot given by rdx + 1. 1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size, 1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::kHeaderSize + kPointerSize)); 1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label feedback_register_initialized; 1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put the AllocationSite from the feedback vector into rbx, or undefined. 1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size, 1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::kHeaderSize)); 1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(FieldOperand(rbx, 0), Heap::kAllocationSiteMapRootIndex); 1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &feedback_register_initialized); 1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); 1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&feedback_register_initialized); 1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertUndefinedOrAllocationSite(rbx); 19793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 19803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Jump to the function-specific construct stub. 1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register jmp_reg = rcx; 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(jmp_reg, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); 1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(jmp_reg, FieldOperand(jmp_reg, 1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kConstructStubOffset)); 1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize)); 1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(jmp_reg); 19883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: called object 19903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax: number of arguments 19913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: object map 19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label do_call; 19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 19943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); 19953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &non_function_call); 19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); 19973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&do_call); 19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&non_function_call); 20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 20013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&do_call); 20023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set expected number of arguments to zero (not changing rax). 20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Set(rbx, 0); 2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Jump(isolate()->builtins()->ArgumentsAdaptorTrampoline(), 20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::CODE_TARGET); 20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 20073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(vector, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset)); 2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(vector, FieldOperand(vector, 2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kFeedbackVectorOffset)); 201444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 201544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 201644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallIC_ArrayStub::Generate(MacroAssembler* masm) { 2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdi - function 2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdx - slot id (as integer) 2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int argc = arg_count(); 2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount actual(argc); 2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadTypeFeedbackVector(masm, rbx); 2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rdx, rdx); 2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx); 2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdi, rcx); 2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &miss); 2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, Immediate(arg_count())); 2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, 2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::kHeaderSize)); 2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Verify that ecx contains an AllocationSite 2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = masm->isolate()->factory(); 2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), 2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory->allocation_site_map()); 2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &miss); 2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, rcx); 2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArrayConstructorStub stub(masm->isolate(), arg_count()); 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&miss); 2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMiss(masm); 2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The slow case, we need this no matter what to complete a call after a miss. 2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionNoFeedback(masm, 2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch arg_count(), 2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch true, 2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallAsMethod()); 2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unreachable. 2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ int3(); 2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallICStub::Generate(MacroAssembler* masm) { 2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdi - function 2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdx - slot id 2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label extra_checks_or_miss, slow_start; 2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow, non_function, wrap, cont; 2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label have_js_function; 2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int argc = arg_count(); 2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, argc); 2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount actual(argc); 2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadTypeFeedbackVector(masm, rbx); 2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The checks. First, does rdi match the recorded monomorphic target? 2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rdx, rdx); 2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdi, FieldOperand(rbx, rdx, times_pointer_size, 2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::kHeaderSize)); 2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &extra_checks_or_miss); 2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&have_js_function); 2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CallAsMethod()) { 2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitContinueIfStrictOrNative(masm, &cont); 2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the receiver from the stack. 2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, args.GetReceiverOperand()); 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(rax, &wrap); 2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); 2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, &wrap); 2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&cont); 2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); 2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitSlowCase(isolate, masm, &args, argc, &non_function); 2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CallAsMethod()) { 2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&wrap); 2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitWrapCase(masm, &args, &cont); 2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&extra_checks_or_miss); 2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, 2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::kHeaderSize)); 2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate)); 2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &slow_start); 2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(rcx, TypeFeedbackVector::UninitializedSentinel(isolate)); 2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &miss); 2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!FLAG_trace_ic) { 2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We are going megamorphic. If the feedback is a JSFunction, it is fine 2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to handle it here. More complex cases are dealt with in the runtime. 2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertNotSmi(rcx); 2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(rcx, JS_FUNCTION_TYPE, rcx); 2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &miss); 2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), 2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackVector::MegamorphicSentinel(isolate)); 2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&slow_start); 2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We are here because tracing is on or we are going monomorphic. 2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&miss); 2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMiss(masm); 2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the slow case 2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow_start); 2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that function is not a smi. 2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(rdi, &non_function); 2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that function is a JSFunction. 2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &slow); 2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&have_js_function); 2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unreachable 2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ int3(); 2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallICStub::GenerateMiss(MacroAssembler* masm) { 2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the receiver of the function from the stack; 1 ~ return address. 2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Operand(rsp, (arg_count() + 1) * kPointerSize)); 2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the receiver and the function and feedback info. 2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rcx); 2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdi); 2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rbx); 2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Integer32ToSmi(rdx, rdx); 2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the entry. 2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss 2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : IC::kCallIC_Customization_Miss; 2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference miss = ExternalReference(IC_Utility(id), 2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()); 2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallExternalReference(miss, 4); 2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move result to edi and exit the internal frame. 2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, rax); 2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool CEntryStub::NeedsImmovableCode() { 2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CEntryStub::GenerateAheadOfTime(isolate); 2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // It is important that the store buffer overflow stubs are generated first. 2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BinaryOpICStub::GenerateAheadOfTime(isolate); 2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeStub::GenerateFPStubs(Isolate* isolate) { 21873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 21883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CEntryStub stub(isolate, 1, kDontSaveFPRegs); 2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stub.GetCode(); 2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CEntryStub save_doubles(isolate, 1, kSaveFPRegs); 2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch save_doubles.GetCode(); 2195592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 2196592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2197592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CEntryStub::Generate(MacroAssembler* masm) { 2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rax: number of arguments including receiver 2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rbx: pointer to C function (C callee-saved) 2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rbp: frame pointer of calling JS frame (restored after C call) 2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp: stack pointer (restored after C call) 2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsi: current context (restored) 2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm); 2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Enter the exit frame that transitions from JavaScript to C++. 2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _WIN64 2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_stack_space = (result_size() < 2 ? 2 : 4); 2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else // _WIN64 2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_stack_space = 0; 2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // _WIN64 2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EnterExitFrame(arg_stack_space, save_doubles()); 2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rbx: pointer to builtin function (C callee-saved). 2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rbp: frame pointer of exit frame (restored after C call). 2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp: stack pointer (restored after C call). 221880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // r14: number of arguments including receiver (C callee-saved). 2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r15: argv pointer (C callee-saved). 222080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 222180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Simple results returned in rax (both AMD64 and Win64 calling conventions). 222280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Complex results must be written to address passed as first argument. 222380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // AMD64 calling convention: a struct of two pointers in rax+rdx 222480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 222580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check stack alignment. 222680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (FLAG_debug_code) { 222780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CheckStackAlignment(); 222880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 222980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 223080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Call C function. 223180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64 2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9. 2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pass argv and argc as two parameters. The arguments object will 2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // be created by stubs declared by DECLARE_RUNTIME_FUNCTION(). 2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result_size() < 2) { 223680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Pass a pointer to the Arguments object as the first argument. 223780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return result in single register (rax). 2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, r14); // argc. 2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, r15); // argv. 2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(r8, ExternalReference::isolate_address(isolate())); 224180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, result_size()); 224380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Pass a pointer to the result location as the first argument. 2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rcx, StackSpaceOperand(2)); 224580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Pass a pointer to the Arguments object as the second argument. 2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, r14); // argc. 2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(r8, r15); // argv. 2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(r9, ExternalReference::isolate_address(isolate())); 224980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 225080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 225180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#else // _WIN64 225280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. 2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, r14); // argc. 2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, r15); // argv. 2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rdx, ExternalReference::isolate_address(isolate())); 2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // _WIN64 225780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ call(rbx); 225880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Result is in rax - do not destroy this register! 225980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 226080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64 226180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If return value is on the stack, pop it to registers. 2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result_size() > 1) { 2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, result_size()); 226480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Read result values stored on stack. Result is stored 226580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // above the four argument mirror slots and the two 226680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Arguments object slots. 2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(rax, Operand(rsp, 6 * kRegisterSize)); 2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(rdx, Operand(rsp, 7 * kRegisterSize)); 226980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // _WIN64 227180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Runtime functions should not return 'the hole'. Allowing it to escape may 2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // lead to crashes in the IC code later. 2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label okay; 2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &okay, Label::kNear); 2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ int3(); 2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&okay); 2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check result for exception sentinel. 2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label exception_returned; 2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rax, Heap::kExceptionRootIndex); 2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &exception_returned); 228680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_exception_address( 2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate::kPendingExceptionAddress, isolate()); 2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that there is no pending exception, otherwise we 2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // should have returned the exception sentinel. 2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label okay; 2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r14, Heap::kTheHoleValueRootIndex); 2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand pending_exception_operand = 2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->ExternalOperand(pending_exception_address); 2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(r14, pending_exception_operand); 2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &okay, Label::kNear); 2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ int3(); 2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&okay); 2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 230280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Exit the JavaScript to C++ exit frame. 2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LeaveExitFrame(save_doubles()); 2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 230680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handling of exception. 2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&exception_returned); 230980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Retrieve the pending exception. 231144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand pending_exception_operand = 231244f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->ExternalOperand(pending_exception_address); 2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, pending_exception_operand); 2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Clear the pending exception. 231644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); 2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(pending_exception_operand, rdx); 231880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 231980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Special handling of termination exceptions which are uncatchable 232080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // by javascript code. 2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label throw_termination_exception; 232280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &throw_termination_exception); 232480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 232580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Handle normal exception. 2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Throw(rax); 232780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 232880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&throw_termination_exception); 23293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ThrowUncatchable(rax); 233080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 233180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 233280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid JSEntryStub::Generate(MacroAssembler* masm) { 23343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label invoke, handler_entry, exit; 233580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label not_outermost_js, not_outermost_js_2; 2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm); 2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 233944f0eee88ff00398ff7f715fab053374d808c90dSteve Block { // NOLINT. Scope block confuses linter. 234044f0eee88ff00398ff7f715fab053374d808c90dSteve Block MacroAssembler::NoRootArrayScope uninitialized_root_register(masm); 23413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up frame. 2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(rbp); 2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbp, rsp); 234444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 234544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Push the stack frame type marker twice. 2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int marker = type(); 234744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Scratch register is neither callee-save, nor an argument register on any 234844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // platform. It's free to use at this point. 234944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Cannot use smi-register for loading yet. 2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(kScratchRegister, Smi::FromInt(marker), Assembler::RelocInfoNone()); 2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(kScratchRegister); // context slot 2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(kScratchRegister); // function slot 2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save callee-saved registers (X64/X32/Win64 calling conventions). 2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(r12); 2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(r13); 2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(r14); 2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(r15); 2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _WIN64 2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(rdi); // Only callee save in Win64 ABI, argument in AMD64 ABI. 2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(rsi); // Only callee save in Win64 ABI, argument in AMD64 ABI. 2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(rbx); 2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 236480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64 2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // On Win64 XMM6-XMM15 are callee-save 2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rsp, Immediate(EntryFrameConstants::kXMMRegistersBlockSize)); 2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0), xmm6); 2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1), xmm7); 2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 2), xmm8); 2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 3), xmm9); 2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 4), xmm10); 2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 5), xmm11); 2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 6), xmm12); 2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 7), xmm13); 2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 8), xmm14); 2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 9), xmm15); 237780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif 237844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 237944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Set up the roots and smi constant registers. 238044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Needs to be done before any further smi loads. 238144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ InitializeSmiConstantRegister(); 238244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ InitializeRootRegister(); 238344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 238480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 238544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Save copies of the top frame descriptor on the stack. 2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference c_entry_fp(Isolate::kCEntryFPAddress, isolate()); 238744f0eee88ff00398ff7f715fab053374d808c90dSteve Block { 238844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp); 2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(c_entry_fp_operand); 239044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 239180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 239280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If this is the outermost JS call, set js_entry_sp value. 2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate()); 239444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Load(rax, js_entry_sp); 2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rax, rax); 239680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, ¬_outermost_js); 2397053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block __ Push(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)); 2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, rbp); 239944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Store(js_entry_sp, rax); 2400053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block Label cont; 2401053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block __ jmp(&cont); 240280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(¬_outermost_js); 2403053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block __ Push(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)); 2404053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block __ bind(&cont); 240580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 24063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Jump to a faked try block that does the invoke, with a faked catch 24073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // block that sets the pending exception. 24083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&invoke); 24093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&handler_entry); 24103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch handler_offset_ = handler_entry.pos(); 24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Caught exception: Store result (exception) in the pending exception 24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // field in the JSEnv and return a failure sentinel. 2413589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ExternalReference pending_exception(Isolate::kPendingExceptionAddress, 2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()); 241544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Store(pending_exception, rax); 2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(rax, Heap::kExceptionRootIndex); 241780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&exit); 241880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 24193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke: Link this frame into the handler chain. There's only one 24203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // handler block in this code object, so its index is 0. 242180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&invoke); 24223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushTryHandler(StackHandler::JS_ENTRY, 0); 242380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 242480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Clear any pending exceptions. 242544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadRoot(rax, Heap::kTheHoleValueRootIndex); 242644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Store(pending_exception, rax); 242780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 242880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Fake a receiver (NULL). 2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Immediate(0)); // receiver 243080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 24313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke the function by calling through JS entry trampoline builtin and 24323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // pop the faked function when we return. We load the address from an 24333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // external reference instead of inlining the call target address directly 24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in the code, because the builtin stubs may not have been generated yet 24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // at the time this code is generated. 2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type() == StackFrame::ENTRY_CONSTRUCT) { 243744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline, 2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()); 243944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Load(rax, construct_entry); 244080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference entry(Builtins::kJSEntryTrampoline, isolate()); 244244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Load(rax, entry); 244380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(kScratchRegister, FieldOperand(rax, Code::kHeaderSize)); 244580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ call(kScratchRegister); 244680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 244780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Unlink this frame from the handler chain. 2448053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block __ PopTryHandler(); 244980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2450053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block __ bind(&exit); 2451053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block // Check if the current stack frame is marked as the outermost JS frame. 2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rbx); 2453053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block __ Cmp(rbx, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)); 245480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, ¬_outermost_js_2); 2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(kScratchRegister, js_entry_sp); 2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(kScratchRegister, 0), Immediate(0)); 245780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(¬_outermost_js_2); 245880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 245980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Restore the top frame descriptor from the stack. 2460053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block { Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp); 2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(c_entry_fp_operand); 246244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 246380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 246480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Restore callee-saved registers (X64 conventions). 2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _WIN64 2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // On Win64 XMM6-XMM15 are callee-save 2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(xmm6, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0)); 2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(xmm7, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1)); 2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(xmm8, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 2)); 2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(xmm9, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 3)); 2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(xmm10, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 4)); 2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(xmm11, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 5)); 2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(xmm12, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 6)); 2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(xmm13, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 7)); 2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(xmm14, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 8)); 2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movdqu(xmm15, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 9)); 2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(EntryFrameConstants::kXMMRegistersBlockSize)); 2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(rbx); 248180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64 248280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI. 2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(rsi); 2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(rdi); 248580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif 2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(r15); 2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(r14); 2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(r13); 2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(r12); 2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(2 * kPointerSize)); // remove markers 249180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 249280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Restore frame pointer and return. 2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(rbp); 249480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ret(0); 249580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 249680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 249780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 249880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid InstanceofStub::Generate(MacroAssembler* masm) { 249980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Implements "value instanceof function" operator. 250044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Expected input state with no inline cache: 2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[0] : return address 2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[8] : function pointer 2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[16] : value 250444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Expected input state with an inline one-element cache: 2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[0] : return address 2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[8] : offset from return address to location of inline cache 2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[16] : function pointer 2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[24] : value 250980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Returns a bitwise zero to indicate that the value 251080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // is and instance of the function and anything else to 251180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // indicate that the value is not an instance. 251280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fixed register usage throughout the stub. 2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = rax; // Object (lhs). 2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map = rbx; // Map of the object. 2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register function = rdx; // Function (rhs). 2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register prototype = rdi; // Prototype of the function. 2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = rcx; 2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 25208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static const int kOffsetToMapCheckValue = 2; 2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kOffsetToResultValue = kPointerSize == kInt64Size ? 18 : 14; 252244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The last 4 bytes of the instruction sequence 2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // movp(rdi, FieldOperand(rax, HeapObject::kMapOffset)) 2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move(kScratchRegister, Factory::the_hole_value()) 252544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // in front of the hole value address. 2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const unsigned int kWordBeforeMapCheckValue = 2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointerSize == kInt64Size ? 0xBA49FF78 : 0xBA41FF78; 252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The last 4 bytes of the instruction sequence 252944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // __ j(not_equal, &cache_miss); 253044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); 253144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // before the offset of the hole value in the root array. 2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const unsigned int kWordBeforeResultValue = 2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointerSize == kInt64Size ? 0x458B4906 : 0x458B4106; 2534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int extra_argument_offset = HasCallSiteInlineCheck() ? 1 : 0; 253644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(object.code(), InstanceofStub::left().code()); 2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(function.code(), InstanceofStub::right().code()); 2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the object and function - they are always both needed. 2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Go slow case if the object is a smi. 2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow; 2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, 2 + extra_argument_offset, 2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ARGUMENTS_DONT_CONTAIN_RECEIVER); 2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!HasArgsInRegisters()) { 2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(object, args.GetArgumentOperand(0)); 2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(function, args.GetArgumentOperand(1)); 2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(object, &slow); 255080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 255180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the left hand is a JS object. Leave its map in rax. 2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(object, FIRST_SPEC_OBJECT_TYPE, map); 255380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(below, &slow); 2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpInstanceType(map, LAST_SPEC_OBJECT_TYPE); 255580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(above, &slow); 255680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 255744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If there is a call site cache don't look in the global cache, but do the 255844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // real lookup and update the call site cache. 2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) { 256044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Look up the function and the map in the instanceof cache. 2561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 2563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss, Label::kNear); 2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex); 2565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss, Label::kNear); 256644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); 2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 256844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss); 256944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 257080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the prototype of the function. 2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TryGetFunctionPrototype(function, prototype, &slow, true); 257380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 257480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the function prototype is a JS object. 2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(prototype, &slow); 2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(prototype, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); 257780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(below, &slow); 25783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpInstanceType(kScratchRegister, LAST_SPEC_OBJECT_TYPE); 257980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(above, &slow); 258080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the global instanceof or call site inlined cache with the current 2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // map and function. The cached answer will be set when it is known below. 258344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!HasCallSiteInlineCheck()) { 2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); 258644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The constants for the code patching are based on push instructions 2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // at the call site. 2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!HasArgsInRegisters()); 25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get return address and delta to inlined map check. 2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(kScratchRegister, StackOperandForReturnAddress(0)); 2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(kScratchRegister, args.GetArgumentOperand(2)); 259344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_debug_code) { 2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movl(scratch, Immediate(kWordBeforeMapCheckValue)); 2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), scratch); 2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck); 259744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(kScratchRegister, 25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(kScratchRegister, kOffsetToMapCheckValue)); 2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(kScratchRegister, 0), map); 260144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 260280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 260380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Loop through the prototype chain looking for the function prototype. 2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, FieldOperand(map, Map::kPrototypeOffset)); 2605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label loop, is_instance, is_not_instance; 260680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex); 260780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&loop); 2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(scratch, prototype); 2609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &is_instance, Label::kNear); 2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(scratch, kScratchRegister); 261180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The code at is_not_instance assumes that kScratchRegister contains a 261280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // non-zero GCable value (the null object in this case). 2613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &is_not_instance, Label::kNear); 2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); 261680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&loop); 261780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 261880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&is_instance); 261944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!HasCallSiteInlineCheck()) { 262044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ xorl(rax, rax); 262144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Store bitwise zero in the cache. This is a Smi in GC terms. 262244f0eee88ff00398ff7f715fab053374d808c90dSteve Block STATIC_ASSERT(kSmiTag == 0); 262344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); 2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ReturnTrueFalseObject()) { 2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(rax, Heap::kTrueValueRootIndex); 2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 262744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 262844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Store offset of true in the root array at the inline check site. 26293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int true_offset = 0x100 + 26303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; 26313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert it is a 1-byte signed value. 2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(true_offset >= 0 && true_offset < 0x100); 26333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movl(rax, Immediate(true_offset)); 2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(kScratchRegister, StackOperandForReturnAddress(0)); 2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(kScratchRegister, args.GetArgumentOperand(2)); 263644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); 263744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_debug_code) { 263844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(rax, Immediate(kWordBeforeResultValue)); 263944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); 2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); 2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!ReturnTrueFalseObject()) { 2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(rax, 0); 264444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 264544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) * 2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointerSize); 264880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 264980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&is_not_instance); 265044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!HasCallSiteInlineCheck()) { 265144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We have to store a non-zero value in the cache. 265244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); 2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ReturnTrueFalseObject()) { 2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(rax, Heap::kFalseValueRootIndex); 2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 265644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 265744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Store offset of false in the root array at the inline check site. 26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int false_offset = 0x100 + 26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; 26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert it is a 1-byte signed value. 2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(false_offset >= 0 && false_offset < 0x100); 26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movl(rax, Immediate(false_offset)); 2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movq(kScratchRegister, StackOperandForReturnAddress(0)); 2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(kScratchRegister, args.GetArgumentOperand(2)); 266544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); 266644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_debug_code) { 266744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(rax, Immediate(kWordBeforeResultValue)); 266844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); 2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); 267044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 267144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) * 2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointerSize); 267480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 267580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Slow-case: Go through the JavaScript implementation. 267680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow); 2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!ReturnTrueFalseObject()) { 2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Tail call the builtin which returns 0 or 1. 2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!HasArgsInRegisters()); 2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (HasCallSiteInlineCheck()) { 2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove extra value from the stack. 2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(rcx); 2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rax); 2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushReturnAddressFrom(rcx); 2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the builtin and convert 0/1 to true/false. 2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(object); 2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(function); 2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); 2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label true_value, done; 2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testq(rax, rax); 2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &true_value, Label::kNear); 2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(rax, Heap::kFalseValueRootIndex); 2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&true_value); 2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(rax, Heap::kTrueValueRootIndex); 2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) * 2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointerSize); 270580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 270680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 270780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 270880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 270980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// ------------------------------------------------------------------------- 271080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// StringCharCodeAtGenerator 271180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 271280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 271380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If the receiver is a smi trigger the non-string case. 271480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfSmi(object_, receiver_not_string_); 271580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 271680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Fetch the instance type of the receiver into result register. 2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(result_, FieldOperand(object_, HeapObject::kMapOffset)); 271880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 271980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If the receiver is not a string trigger the non-string case. 272080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(result_, Immediate(kIsNotStringMask)); 272180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, receiver_not_string_); 272280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 272380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If the index is non-smi trigger the non-smi case. 272480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfNotSmi(index_, &index_not_smi_); 272580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&got_smi_index_); 272680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 272780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for index out of range. 27283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiCompare(index_, FieldOperand(object_, String::kLengthOffset)); 272980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(above_equal, index_out_of_range_); 273080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 27313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(index_, index_); 273280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharLoadGenerator::Generate( 27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, object_, index_, result_, &call_runtime_); 273569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 273680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Integer32ToSmi(result_, result_); 273780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&exit_); 273880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 273980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 274080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 274180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringCharCodeAtGenerator::GenerateSlow( 27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const RuntimeCallHelper& call_helper) { 2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase); 274580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Factory* factory = masm->isolate()->factory(); 274780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Index is not a smi. 274880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&index_not_smi_); 274980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If index is a heap number, try converting it to an integer. 2750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(index_, 2751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch factory->heap_number_map(), 2752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch index_not_number_, 2753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DONT_DO_SMI_CHECK); 275480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen call_helper.BeforeCall(masm); 2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(object_); 2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(index_); // Consumed by runtime conversion function. 275780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (index_flags_ == STRING_INDEX_IS_NUMBER) { 275880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); 275980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 276180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // NumberToSmi discards numbers that are not exact integers. 276280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallRuntime(Runtime::kNumberToSmi, 1); 276380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!index_.is(rax)) { 276580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Save the conversion result before the pop instructions below 276680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // have a chance to overwrite it. 2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(index_, rax); 276880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(object_); 277080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Reload the instance type. 2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(result_, FieldOperand(object_, HeapObject::kMapOffset)); 277280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 277380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen call_helper.AfterCall(masm); 277480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If index is still not a smi, it must be out of range. 27753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(index_, index_out_of_range_); 277680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Otherwise, return to the fast path. 277780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&got_smi_index_); 277880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 277980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Call runtime. We get here when the receiver is a string and the 278080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // index is a number, but the code of getting the actual character 278180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // is too complex (e.g., when the string needs to be flattened). 278280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&call_runtime_); 278380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen call_helper.BeforeCall(masm); 2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(object_); 27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Integer32ToSmi(index_, index_); 2786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(index_); 2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kStringCharCodeAtRT, 2); 278880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (!result_.is(rax)) { 2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(result_, rax); 279080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 279180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen call_helper.AfterCall(masm); 279280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&exit_); 279380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); 279580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 279680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 279780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 279880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// ------------------------------------------------------------------------- 279980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// StringCharFromCodeGenerator 280080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 280180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 280280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Fast case of Heap::LookupSingleCharacterStringFromCode. 280380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfNotSmi(code_, &slow_case_); 2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiCompare(code_, Smi::FromInt(String::kMaxOneByteCharCode)); 280580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(above, &slow_case_); 280680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 280780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); 280880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SmiIndex index = masm->SmiToIndex(kScratchRegister, code_, kPointerSizeLog2); 2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(result_, FieldOperand(result_, index.reg, index.scale, 281080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen FixedArray::kHeaderSize)); 281180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(result_, Heap::kUndefinedValueRootIndex); 281280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, &slow_case_); 281380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&exit_); 281480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 281580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 281680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 281780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringCharFromCodeGenerator::GenerateSlow( 28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const RuntimeCallHelper& call_helper) { 2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); 282180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 282280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case_); 282380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen call_helper.BeforeCall(masm); 2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(code_); 282580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallRuntime(Runtime::kCharFromCode, 1); 282680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (!result_.is(rax)) { 2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(result_, rax); 282880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 282980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen call_helper.AfterCall(masm); 283080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&exit_); 283180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 283380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 283480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 283580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 283680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringHelper::GenerateCopyCharacters(MacroAssembler* masm, 283780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register dest, 283880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register src, 283980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register count, 2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String::Encoding encoding) { 284180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Nothing to do for zero characters. 2842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 284380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testl(count, count); 2844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &done, Label::kNear); 284580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 284680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Make count the number of bytes to copy. 2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (encoding == String::TWO_BYTE_ENCODING) { 284880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen STATIC_ASSERT(2 == sizeof(uc16)); 284980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ addl(count, count); 285080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 285180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 285280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Copy remaining characters. 285380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label loop; 285480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&loop); 285580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movb(kScratchRegister, Operand(src, 0)); 285680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movb(Operand(dest, 0), kScratchRegister); 2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ incp(src); 2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ incp(dest); 285980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ decl(count); 286080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, &loop); 286180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 286280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 286380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 286480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 286580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 286680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid SubStringStub::Generate(MacroAssembler* masm) { 286780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label runtime; 286880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 286980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Stack frame on entry. 2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[0] : return address 2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[8] : to 2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[16] : from 2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[24] : string 287480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum SubStringStubArgumentIndices { 2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STRING_ARGUMENT_INDEX, 2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FROM_ARGUMENT_INDEX, 2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TO_ARGUMENT_INDEX, 2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SUB_STRING_ARGUMENT_COUNT 2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, SUB_STRING_ARGUMENT_COUNT, 2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ARGUMENTS_DONT_CONTAIN_RECEIVER); 288480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 288580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Make sure first argument is a string. 2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, args.GetArgumentOperand(STRING_ARGUMENT_INDEX)); 288780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen STATIC_ASSERT(kSmiTag == 0); 288880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testl(rax, Immediate(kSmiTagMask)); 288980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, &runtime); 289080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); 289180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(NegateCondition(is_string), &runtime); 289280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 289380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rax: string 289480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rbx: instance type 289580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Calculate length of sub string using the smi values. 2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, args.GetArgumentOperand(TO_ARGUMENT_INDEX)); 2897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, args.GetArgumentOperand(FROM_ARGUMENT_INDEX)); 2898f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime); 289980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 29000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ SmiSub(rcx, rcx, rdx); // Overflow doesn't happen. 2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rcx, FieldOperand(rax, String::kLengthOffset)); 29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label not_original_string; 2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Shorter than original string's length: an actual substring. 2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, ¬_original_string, Label::kNear); 2905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Longer than original string's length or negative: unsafe arguments. 2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, &runtime); 2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return original string. 2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = isolate()->counters(); 29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->sub_string_native(), 1); 2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); 29113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_original_string); 291280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label single_char; 2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiCompare(rcx, Smi::FromInt(1)); 2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &single_char); 291680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rcx, rcx); 29183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax: string 29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rbx: instance type 29213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: sub string length 29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: from index (smi) 29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Deal with different string types: update the index if necessary 29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and put the underlying string into edi. 29253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label underlying_unpacked, sliced_string, seq_or_external_string; 29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the string is not indirect, it can only be sequential or external. 29273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); 29283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kIsIndirectStringMask != 0); 29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(rbx, Immediate(kIsIndirectStringMask)); 29303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(zero, &seq_or_external_string, Label::kNear); 29313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(rbx, Immediate(kSlicedNotConsMask)); 29333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_zero, &sliced_string, Label::kNear); 29343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cons string. Check whether it is flat, then fetch first part. 29353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Flat cons strings have an empty second part. 29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset), 2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kempty_stringRootIndex); 29383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &runtime); 2939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, FieldOperand(rax, ConsString::kFirstOffset)); 29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update instance type. 2941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 294280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 29433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&underlying_unpacked, Label::kNear); 29443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&sliced_string); 29463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sliced string. Fetch parent and correct start index by offset. 2947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rdx, FieldOperand(rax, SlicedString::kOffsetOffset)); 2948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, FieldOperand(rax, SlicedString::kParentOffset)); 29493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update instance type. 2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 29513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 29523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&underlying_unpacked, Label::kNear); 29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&seq_or_external_string); 29553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Sequential or external string. Just move string to the correct register. 2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, rax); 29573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&underlying_unpacked); 295980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2960589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (FLAG_string_slices) { 2961589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label copy_routine; 29623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: underlying subject string 29633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rbx: instance type of underlying subject string 29643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: adjusted start index (smi) 29653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: length 2966589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // If coming from the make_two_character_string path, the string 2967589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // is too short to be sliced anyways. 2968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rcx, Immediate(SlicedString::kMinLength)); 2969589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Short slice. Copy instead of slicing. 2970589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ j(less, ©_routine); 2971589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Allocate new sliced string. At this point we do not reload the instance 2972589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // type including the string encoding because we simply rely on the info 2973589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // provided by the original string. It does not matter if the original 2974589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // string's encoding is wrong because we always have to recheck encoding of 2975589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // the newly created string's parent anyways due to externalized strings. 2976589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label two_byte_slice, set_slice_header; 2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); 2978589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 2979589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ testb(rbx, Immediate(kStringEncodingMask)); 2980589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ j(zero, &two_byte_slice, Label::kNear); 2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateOneByteSlicedString(rax, rbx, r14, &runtime); 2982589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ jmp(&set_slice_header, Label::kNear); 2983589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&two_byte_slice); 29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateTwoByteSlicedString(rax, rbx, r14, &runtime); 2985589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&set_slice_header); 2986589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Integer32ToSmi(rcx, rcx); 2987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, SlicedString::kLengthOffset), rcx); 2988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, SlicedString::kHashFieldOffset), 2989589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Immediate(String::kEmptyHashField)); 2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, SlicedString::kParentOffset), rdi); 2991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, SlicedString::kOffsetOffset), rdx); 29923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->sub_string_native(), 1); 2993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(3 * kPointerSize); 2994589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2995589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(©_routine); 2996589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 299780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: underlying subject string 29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rbx: instance type of underlying subject string 30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: adjusted start index (smi) 30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: length 30023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The subject string can only be external or sequential string of either 30033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // encoding at this point. 30043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label two_byte_sequential, sequential_string; 30053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kExternalStringTag != 0); 30063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSeqStringTag == 0); 30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(rbx, Immediate(kExternalStringTag)); 30083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(zero, &sequential_string); 30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle external string. 30113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Rule out short external strings. 3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kShortExternalStringTag != 0); 30133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(rbx, Immediate(kShortExternalStringMask)); 30143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_zero, &runtime); 3015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); 30163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Move the pointer so that offset-wise, it looks like a sequential string. 3017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&sequential_string); 3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); 30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(rbx, Immediate(kStringEncodingMask)); 30233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(zero, &two_byte_sequential); 302480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 302580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Allocate the result. 3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateOneByteString(rax, rcx, r11, r14, r15, &runtime); 302780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 302880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rax: result string 302980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rcx: result string length 30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { // Locate character of sub string start. 30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_1); 3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(r14, Operand(rdi, smi_as_index.reg, smi_as_index.scale, 3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SeqOneByteString::kHeaderSize - kHeapObjectTag)); 303485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Locate first character of result. 3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize)); 303780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 303880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rax: result string 303980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rcx: result length 3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r14: first character of result 304180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rsi: character of sub string start 3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringHelper::GenerateCopyCharacters( 3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, rdi, r14, rcx, String::ONE_BYTE_ENCODING); 304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->sub_string_native(), 1); 3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); 304680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 30473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&two_byte_sequential); 304880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Allocate the result. 30493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime); 305080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 305180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rax: result string 305280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rcx: result string length 30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { // Locate character of sub string start. 30543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2); 3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(r14, Operand(rdi, smi_as_index.reg, smi_as_index.scale, 3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SeqOneByteString::kHeaderSize - kHeapObjectTag)); 305785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 30583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Locate first character of result. 3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); 306080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 306180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rax: result string 306280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rcx: result length 306380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rdi: first character of result 3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r14: character of sub string start 3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringHelper::GenerateCopyCharacters( 3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, rdi, r14, rcx, String::TWO_BYTE_ENCODING); 306744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->sub_string_native(), 1); 3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); 306980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 307080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Just jump to runtime to create the sub string. 307180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&runtime); 307280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ TailCallRuntime(Runtime::kSubString, 3, 1); 3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&single_char); 3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rax: string 3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rbx: instance type 3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rcx: sub string length (smi) 3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdx: from index (smi) 3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringCharAtGenerator generator( 3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rax, rdx, rcx, rax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); 3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.GenerateFast(masm); 3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); 3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.SkipSlow(masm, &runtime); 308480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 308580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 308680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, 3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left, 3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register right, 3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2) { 3092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register length = scratch1; 3093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare lengths. 3095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label check_zero_length; 3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(length, FieldOperand(left, String::kLengthOffset)); 3097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiCompare(length, FieldOperand(right, String::kLengthOffset)); 3098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &check_zero_length, Label::kNear); 3099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(rax, Smi::FromInt(NOT_EQUAL)); 3100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the length is zero. 3103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label compare_chars; 3104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&check_zero_length); 3105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 3106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiTest(length); 3107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &compare_chars, Label::kNear); 3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(rax, Smi::FromInt(EQUAL)); 3109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare characters. 3112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&compare_chars); 3113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label strings_not_equal; 3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, 3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &strings_not_equal, Label::kNear); 3116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Characters are equal. 3118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(rax, Smi::FromInt(EQUAL)); 3119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Characters are not equal. 3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&strings_not_equal); 3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(rax, Smi::FromInt(NOT_EQUAL)); 3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StringHelper::GenerateCompareFlatOneByteStrings( 3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register left, Register right, Register scratch1, 3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, Register scratch3, Register scratch4) { 313180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Ensure that you can always subtract a string length from a non-negative 313280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // number (e.g. another length). 313380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen STATIC_ASSERT(String::kMaxLength < 0x7fffffff); 313480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 313580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Find minimum length and length difference. 3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch1, FieldOperand(left, String::kLengthOffset)); 3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch4, scratch1); 313880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiSub(scratch4, 313980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen scratch4, 31400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen FieldOperand(right, String::kLengthOffset)); 314180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Register scratch4 now holds left.length - right.length. 314280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen const Register length_difference = scratch4; 3143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label left_shorter; 3144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(less, &left_shorter, Label::kNear); 314580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The right string isn't longer that the left one. 314680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Get the right string's length by subtracting the (non-negative) difference 314780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // from the left string's length. 31480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ SmiSub(scratch1, scratch1, length_difference); 314980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&left_shorter); 315080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Register scratch1 now holds Min(left.length, right.length). 315180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen const Register min_length = scratch1; 315280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label compare_lengths; 315480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If min-length is zero, go directly to comparing lengths. 315580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiTest(min_length); 3156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &compare_lengths, Label::kNear); 315780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare loop. 3159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label result_not_equal; 3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateOneByteCharsCompareLoop( 3161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, left, right, min_length, scratch2, &result_not_equal, 3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In debug-code mode, SmiTest below might push 3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the target label outside the near range. 3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::kFar); 316580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 316680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Completed loop without finding different characters. 316780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Compare lengths (precomputed). 316880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&compare_lengths); 316980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiTest(length_difference); 3170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label length_not_equal; 3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &length_not_equal, Label::kNear); 317280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 317380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Result is EQUAL. 317480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Move(rax, Smi::FromInt(EQUAL)); 317580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ret(0); 317680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label result_greater; 3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label result_less; 3179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&length_not_equal); 3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(greater, &result_greater, Label::kNear); 3181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&result_less, Label::kNear); 318280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&result_not_equal); 318380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Unequal comparison of left to right, either character or length. 3184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, &result_greater, Label::kNear); 3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&result_less); 318680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 318780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Result is LESS. 318880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Move(rax, Smi::FromInt(LESS)); 318980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ret(0); 319080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 319180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Result is GREATER. 319280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&result_greater); 319380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Move(rax, Smi::FromInt(GREATER)); 319480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ret(0); 319580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 319680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 319780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StringHelper::GenerateOneByteCharsCompareLoop( 3199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register left, Register right, Register length, 3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, Label* chars_not_equal, Label::Distance near_jump) { 3201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Change index to run from -length to -1 by adding length to string 3202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // start. This means that loop ends when index reaches zero, which 3203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // doesn't need an additional compare. 3204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiToInteger32(length, length); 3205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(left, 3206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize)); 3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(right, 3208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(right, length, times_1, SeqOneByteString::kHeaderSize)); 3209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ negq(length); 3210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register index = length; // index = -length; 3211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare loop. 3213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label loop; 3214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&loop); 3215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movb(scratch, Operand(left, index, times_1, 0)); 3216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpb(scratch, Operand(right, index, times_1, 0)); 3217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, chars_not_equal, near_jump); 32183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ incq(index); 3219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &loop); 3220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 322380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringCompareStub::Generate(MacroAssembler* masm) { 322480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label runtime; 322580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 322680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Stack frame on entry. 3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[0] : return address 3228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[8] : right string 3229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[16] : left string 323080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); 3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, args.GetArgumentOperand(0)); // left 3233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, args.GetArgumentOperand(1)); // right 323480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 323580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for identity. 3236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_same; 3237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdx, rax); 3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, ¬_same, Label::kNear); 323980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Move(rax, Smi::FromInt(EQUAL)); 3240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = isolate()->counters(); 324144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_compare_native(), 1); 324280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ret(2 * kPointerSize); 324380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 324480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(¬_same); 324580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that both are sequential one-byte strings. 3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotBothSequentialOneByteStrings(rdx, rax, rcx, rbx, &runtime); 324880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Inline comparison of one-byte strings. 325044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_compare_native(), 1); 325180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Drop arguments from the stack 3252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(rcx); 3253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(2 * kPointerSize)); 3254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushReturnAddressFrom(rcx); 3255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringHelper::GenerateCompareFlatOneByteStrings(masm, rdx, rax, rcx, rbx, rdi, 3256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r8); 325780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 325880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 325980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // tagged as a small integer. 326080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&runtime); 326180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 326280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 326380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3264e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { 3266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 3267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rdx : left 3268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rax : right 3269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[0] : return address 3270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 3271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load rcx with the allocation site. We stick an undefined dummy value here 3273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and replace it with the real allocation site later when we instantiate this 3274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate(). 3275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rcx, handle(isolate()->heap()->undefined_value())); 3276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure that we actually patched the allocation site. 3278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 3279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testb(rcx, Immediate(kSmiTagMask)); 3280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(not_equal, kExpectedAllocationSite); 3281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), 3282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->factory()->allocation_site_map()); 3283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kExpectedAllocationSite); 3284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Tail call into the stub that handles binary operations with allocation 3287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sites. 3288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BinaryOpWithAllocationSiteStub stub(isolate(), state()); 3289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 3290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateSmis(MacroAssembler* masm) { 3294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(state() == CompareICState::SMI); 3295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); 32971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (GetCondition() == equal) { 32991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For equality we do not care about the sign of the result. 3300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rax, rdx); 33011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rdx, rax); 3304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(no_overflow, &done, Label::kNear); 33051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Correct sign of result in case of overflow. 3306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ notp(rdx); 33071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, rdx); 33091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 33111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&miss); 33131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateMiss(masm); 3314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateNumbers(MacroAssembler* masm) { 3318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(state() == CompareICState::NUMBER); 33191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label generic_stub; 33213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label unordered, maybe_undefined1, maybe_undefined2; 3322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 33231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (left() == CompareICState::SMI) { 3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(rdx, &miss); 3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right() == CompareICState::SMI) { 3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(rax, &miss); 3329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load left and right operand. 3332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, left, left_smi, right_smi; 3333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(rax, &right_smi, Label::kNear); 3334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareMap(rax, isolate()->factory()->heap_number_map()); 33353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &maybe_undefined1, Label::kNear); 3336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); 3337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&left, Label::kNear); 3338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&right_smi); 3339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rcx, rax); // Can't clobber rax yet. 3340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtlsi2sd(xmm1, rcx); 3341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&left); 3343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(rdx, &left_smi, Label::kNear); 3344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareMap(rdx, isolate()->factory()->heap_number_map()); 33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &maybe_undefined2, Label::kNear); 33461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); 3347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 3348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&left_smi); 3349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rcx, rdx); // Can't clobber rdx yet. 3350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtlsi2sd(xmm0, rcx); 33511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 33531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Compare operands 33541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ucomisd(xmm0, xmm1); 33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Don't base result on EFLAGS when a NaN is involved. 3357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(parity_even, &unordered, Label::kNear); 33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Return a result of -1, 0, or 1, based on EFLAGS. 33601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Performing mov, because xor would destroy the flag register. 33611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movl(rax, Immediate(0)); 33621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movl(rcx, Immediate(0)); 33631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ setcc(above, rax); // Add one to zero if carry clear and not equal. 3364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sbbp(rax, rcx); // Subtract one if below (aka. carry set). 33651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 33661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&unordered); 33681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&generic_stub); 3369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompareICStub stub(isolate(), op(), CompareICState::GENERIC, 3370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompareICState::GENERIC, CompareICState::GENERIC); 33711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); 33721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&maybe_undefined1); 3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Token::IsOrderedRelationalCompareOp(op())) { 3375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(rax, isolate()->factory()->undefined_value()); 33763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss); 3377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(rdx, &unordered); 33783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); 33793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &maybe_undefined2, Label::kNear); 33803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&unordered); 33813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 33823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&maybe_undefined2); 3384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Token::IsOrderedRelationalCompareOp(op())) { 3385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(rdx, isolate()->factory()->undefined_value()); 33863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &unordered); 33873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 33883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&miss); 33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateMiss(masm); 3391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { 3395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(state() == CompareICState::INTERNALIZED_STRING); 3396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(GetCondition() == equal); 3397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Registers containing left and right operands respectively. 3399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left = rdx; 3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register right = rax; 3401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register tmp1 = rcx; 3402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register tmp2 = rbx; 3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that both operands are heap objects. 3405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = masm->CheckEitherSmi(left, right, tmp1); 3407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(cond, &miss, Label::kNear); 3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that both operands are internalized strings. 3410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 3411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 3412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 3413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 3414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 3415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orp(tmp1, tmp2); 3416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testb(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); 3417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &miss, Label::kNear); 3418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Internalized strings are compared by identity. 3420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 3421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(left, right); 3422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure rax is non-zero. At this point input operands are 3423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // guaranteed to be non-zero. 3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(right.is(rax)); 3425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &done, Label::kNear); 3426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(EQUAL == 0); 3427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 3428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rax, Smi::FromInt(EQUAL)); 3429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 3430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 3431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&miss); 3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMiss(masm); 3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { 3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(state() == CompareICState::UNIQUE_NAME); 3439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(GetCondition() == equal); 3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers containing left and right operands respectively. 3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = rdx; 3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right = rax; 3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp1 = rcx; 3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp2 = rbx; 3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both operands are heap objects. 3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition cond = masm->CheckEitherSmi(left, right, tmp1); 3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(cond, &miss, Label::kNear); 3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that both operands are unique names. This leaves the instance 3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // types loaded in tmp1 and tmp2. 3454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 3457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 3458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotUniqueNameInstanceType(tmp1, &miss, Label::kNear); 3460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotUniqueNameInstanceType(tmp2, &miss, Label::kNear); 3461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unique names are compared by identity. 3463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 3464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(left, right); 3465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure rax is non-zero. At this point input operands are 3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // guaranteed to be non-zero. 3467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(right.is(rax)); 3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &done, Label::kNear); 3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(EQUAL == 0); 3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 3471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(rax, Smi::FromInt(EQUAL)); 3472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 3473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateMiss(masm); 3477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateStrings(MacroAssembler* masm) { 3481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(state() == CompareICState::STRING); 3482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool equality = Token::IsEqualityOp(op()); 34853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers containing left and right operands respectively. 3487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = rdx; 3488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right = rax; 3489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp1 = rcx; 3490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp2 = rbx; 3491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp3 = rdi; 3492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both operands are heap objects. 3494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Condition cond = masm->CheckEitherSmi(left, right, tmp1); 3495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(cond, &miss); 3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that both operands are strings. This leaves the instance 3498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // types loaded in tmp1 and tmp2. 3499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 3500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 3501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 3503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(tmp3, tmp1); 3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kNotStringTag != 0); 3505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orp(tmp3, tmp2); 3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testb(tmp3, Immediate(kIsNotStringMask)); 3507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &miss); 3508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fast check for identical strings. 3510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_same; 3511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(left, right); 3512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, ¬_same, Label::kNear); 3513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(EQUAL == 0); 3514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 3515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(rax, Smi::FromInt(EQUAL)); 3516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle not identical strings. 3519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_same); 3520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that both strings are internalized strings. If they are, we're done 3522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // because we already know they are not identical. We also know they are both 3523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // strings. 35243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (equality) { 35253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label do_compare; 3526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kInternalizedTag == 0); 3527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orp(tmp1, tmp2); 3528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testb(tmp1, Immediate(kIsNotInternalizedMask)); 3529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &do_compare, Label::kNear); 35303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure rax is non-zero. At this point input operands are 35313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // guaranteed to be non-zero. 3532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(right.is(rax)); 35333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 35343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&do_compare); 35353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that both strings are sequential one-byte. 3538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label runtime; 3539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotBothSequentialOneByteStrings(left, right, tmp1, tmp2, &runtime); 3540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compare flat one-byte strings. Returns when done. 35423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (equality) { 3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, 3544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tmp2); 35453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 3546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringHelper::GenerateCompareFlatOneByteStrings( 35473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, left, right, tmp1, tmp2, tmp3, kScratchRegister); 35483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle more complex cases in runtime. 3551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&runtime); 3552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(tmp1); 3553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(left); 3554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(right); 3555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushReturnAddressFrom(tmp1); 35563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (equality) { 35573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallRuntime(Runtime::kStringEquals, 2, 1); 35583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 35593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 35603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 3563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateMiss(masm); 3564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateObjects(MacroAssembler* masm) { 3568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(state() == CompareICState::OBJECT); 3569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 35701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition either_smi = masm->CheckEitherSmi(rdx, rax); 3571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(either_smi, &miss, Label::kNear); 35721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); 3574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss, Label::kNear); 35751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); 3576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss, Label::kNear); 35771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(GetCondition() == equal); 3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rax, rdx); 35801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 35811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&miss); 35831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateMiss(masm); 3584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { 35883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss; 35893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition either_smi = masm->CheckEitherSmi(rdx, rax); 35903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(either_smi, &miss, Label::kNear); 3591c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset)); 3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); 35943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rcx, known_map_); 35953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss, Label::kNear); 35963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rbx, known_map_); 35973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss, Label::kNear); 35981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rax, rdx); 36003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 360185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 36023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&miss); 36033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMiss(masm); 36043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 36053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateMiss(MacroAssembler* masm) { 36083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 36093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call the runtime system in a fresh internal frame. 36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference miss = 3611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); 36123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 3614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 3615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 3616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 3617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 3618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(op())); 36193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallExternalReference(miss, 3); 36203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the entry point of the rewritten stub. 3622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rdi, FieldOperand(rax, Code::kHeaderSize)); 3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rax); 3624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdx); 36253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 36261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Do a tail call to the rewritten stub. 36281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ jmp(rdi); 36291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 36301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, 3633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* miss, 3634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* done, 3635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register properties, 3636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, 3637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register r0) { 3638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name->IsUniqueName()); 3639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If names of slots in range from 1 to kProbes - 1 for the hash value are 3640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // not equal to the name and kProbes-th slot is not used (its name is the 3641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // undefined value), it guarantees the hash table doesn't contain the 3642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // property. It's true even if some slots represent deleted properties 36433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // (their names are the hole value). 3644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < kInlinedProbes; i++) { 3645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // r0 points to properties hash. 3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute the masked index: (hash + i + i * i) & mask. 3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register index = r0; 3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Capacity is smi 2^n. 3649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset)); 3650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ decl(index); 3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ andp(index, 3652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(name->Hash() + NameDictionary::GetProbeOffset(i))); 3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Scale the index by multiplying by the entry size. 3655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(NameDictionary::kEntrySize == 3); 3656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(index, Operand(index, index, times_2, 0)); // index *= 3. 3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register entity_name = r0; 3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Having undefined at this place means the name is not contained. 3660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(kSmiTagSize, 1); 3661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(entity_name, Operand(properties, 3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch index, 3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch times_pointer_size, 3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kElementsStartOffset - kHeapObjectTag)); 3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Cmp(entity_name, masm->isolate()->factory()->undefined_value()); 3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, done); 3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stop if found the property. 3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(entity_name, Handle<Name>(name)); 3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, miss); 3671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label good; 36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the hole and skip. 36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex); 3675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &good, Label::kNear); 36763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the entry name is not a unique name. 3678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); 3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotUniqueNameInstanceType( 3680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(entity_name, Map::kInstanceTypeOffset), miss); 3681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&good); 3682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub stub(masm->isolate(), properties, r0, r0, 3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NEGATIVE_LOOKUP); 3686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(Handle<Object>(name)); 3687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Immediate(name->Hash())); 36883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 3689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(r0, r0); 3690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, miss); 3691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(done); 3692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Probe the name dictionary in the |elements| register. Jump to the 3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// |done| label if a property with the given name is found leaving the 3697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// index into the dictionary in |r1|. Jump to the |miss| label 3698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// otherwise. 3699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, 3700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* miss, 3701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* done, 3702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements, 3703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name, 3704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register r0, 3705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register r1) { 3706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!elements.is(r0)); 3707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!elements.is(r1)); 3708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!name.is(r0)); 3709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!name.is(r1)); 3710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertName(name); 3712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset)); 3714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ decl(r0); 3715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < kInlinedProbes; i++) { 3717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute the masked index: (hash + i + i * i) & mask. 3718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movl(r1, FieldOperand(name, Name::kHashFieldOffset)); 3719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shrl(r1, Immediate(Name::kHashShift)); 3720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i > 0) { 3721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addl(r1, Immediate(NameDictionary::GetProbeOffset(i))); 3722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ andp(r1, r0); 3724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Scale the index by multiplying by the entry size. 3726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(NameDictionary::kEntrySize == 3); 3727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 3728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the key is identical to the name. 3730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(name, Operand(elements, r1, times_pointer_size, 3731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kElementsStartOffset - kHeapObjectTag)); 3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, done); 3733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub stub(masm->isolate(), elements, r0, r1, 3736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch POSITIVE_LOOKUP); 3737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(name); 3738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movl(r0, FieldOperand(name, Name::kHashFieldOffset)); 3739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shrl(r0, Immediate(Name::kHashShift)); 3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r0); 3741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CallStub(&stub); 3742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(r0, r0); 3744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, miss); 3745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(done); 3746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NameDictionaryLookupStub::Generate(MacroAssembler* masm) { 37503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This stub overrides SometimesSetsUpAFrame() to return false. That means 37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // we cannot call anything that could cause a GC from this stub. 3752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stack frame on entry: 3753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[0 * kPointerSize] : return address. 3754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[1 * kPointerSize] : key's hash. 3755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[2 * kPointerSize] : key. 3756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers: 3757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // dictionary_: NameDictionary to probe. 3758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // result_: used as scratch. 3759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // index_: will hold an index of entry if lookup is successful. 3760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // might alias with result_. 3761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Returns: 3762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // result_ is zero if lookup failed, non zero otherwise. 3763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label in_dictionary, maybe_in_dictionary, not_in_dictionary; 3765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = result(); 3767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(scratch, FieldOperand(dictionary(), kCapacityOffset)); 3769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ decl(scratch); 3770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch); 3771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If names of slots in range from 1 to kProbes - 1 for the hash value are 3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // not equal to the name and kProbes-th slot is not used (its name is the 3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // undefined value), it guarantees the hash table doesn't contain the 3775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // property. It's true even if some slots represent deleted properties 3776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // (their names are the null value). 3777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER, 3778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointerSize); 3779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = kInlinedProbes; i < kTotalProbes; i++) { 3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute the masked index: (hash + i + i * i) & mask. 3781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, args.GetArgumentOperand(1)); 3782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i > 0) { 3783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i))); 3784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ andp(scratch, Operand(rsp, 0)); 3786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Scale the index by multiplying by the entry size. 3788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(NameDictionary::kEntrySize == 3); 3789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(index(), Operand(scratch, scratch, times_2, 0)); // index *= 3. 3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Having undefined at this place means the name is not contained. 3792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, Operand(dictionary(), index(), times_pointer_size, 3793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kElementsStartOffset - kHeapObjectTag)); 3794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(scratch, isolate()->factory()->undefined_value()); 3796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, ¬_in_dictionary); 3797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stop if found the property. 3799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(scratch, args.GetArgumentOperand(0)); 3800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &in_dictionary); 3801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) { 3803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we hit a key that is not a unique name during negative 3804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // lookup we have to bailout as this key might be equal to the 3805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // key we are looking for. 3806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the entry name is not a unique name. 3808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 3809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotUniqueNameInstanceType( 3810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(scratch, Map::kInstanceTypeOffset), 3811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &maybe_in_dictionary); 3812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&maybe_in_dictionary); 3816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If we are doing negative lookup then probing failure should be 3817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // treated as a lookup success. For positive lookup probing failure 3818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // should be treated as lookup failure. 3819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode() == POSITIVE_LOOKUP) { 3820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, Immediate(0)); 3821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(1); 3822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(2 * kPointerSize); 3823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&in_dictionary); 3826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, Immediate(1)); 3827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(1); 3828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(2 * kPointerSize); 3829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_in_dictionary); 3831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, Immediate(0)); 3832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(1); 3833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(2 * kPointerSize); 3834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 3838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate) { 3839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs); 3840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stub1.GetCode(); 3841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreBufferOverflowStub stub2(isolate, kSaveFPRegs); 3842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stub2.GetCode(); 38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 38443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Takes the input in 3 registers: address_ value_ and object_. A pointer to 38473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// the value has just been written into the object, now this stub makes sure 38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// we keep the GC informed. The word in the object where the value has been 38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// written is in the address register. 38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RecordWriteStub::Generate(MacroAssembler* masm) { 38513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label skip_to_incremental_noncompacting; 38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label skip_to_incremental_compacting; 38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The first two instructions are generated with labels so as to get the 38553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // offset fixed up correctly by the bind(Label*) call. We patch it back and 38563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // forth between a compare instructions (a nop in this position) and the 38573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // real branch when we start and stop incremental heap marking. 38583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // See RecordWriteStub::Patch for details. 38593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&skip_to_incremental_noncompacting, Label::kNear); 38603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&skip_to_incremental_compacting, Label::kFar); 38613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (remembered_set_action() == EMIT_REMEMBERED_SET) { 3863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 38643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler::kReturnAtEnd); 38653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 38663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 38673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 38683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&skip_to_incremental_noncompacting); 38703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateIncremental(masm, INCREMENTAL); 38713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&skip_to_incremental_compacting); 38733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateIncremental(masm, INCREMENTAL_COMPACTION); 38743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. 38763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Will be checked in IncrementalMarking::ActivateGeneratedStub. 38773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->set_byte_at(0, kTwoByteNopInstruction); 38783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->set_byte_at(2, kFiveByteNopInstruction); 38793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 38803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { 38833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.Save(masm); 38843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (remembered_set_action() == EMIT_REMEMBERED_SET) { 38863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label dont_need_remembered_set; 38873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(regs_.scratch0(), Operand(regs_.address(), 0)); 38893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotInNewSpace(regs_.scratch0(), 38903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch0(), 38913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &dont_need_remembered_set); 38923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckPageFlag(regs_.object(), 38943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch0(), 38953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1 << MemoryChunk::SCAN_ON_SCAVENGE, 38963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch not_zero, 38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &dont_need_remembered_set); 38983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First notify the incremental marker if necessary, then update the 39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // remembered set. 39013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckNeedsToInformIncrementalMarker( 39023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); 3903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InformIncrementalMarker(masm); 39043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.Restore(masm); 3905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 39063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler::kReturnAtEnd); 39073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&dont_need_remembered_set); 39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 39103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckNeedsToInformIncrementalMarker( 39123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, kReturnOnNoNeedToInformIncrementalMarker, mode); 3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InformIncrementalMarker(masm); 39143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.Restore(masm); 39153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 39163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 39173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { 3920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode()); 39213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address = 3922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch arg_reg_1.is(regs_.address()) ? kScratchRegister : regs_.address(); 3923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!address.is(regs_.object())); 3924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!address.is(arg_reg_1)); 39253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(address, regs_.address()); 3926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(arg_reg_1, regs_.object()); 3927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(gc) Can we just set address arg2 in the beginning? 3928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(arg_reg_2, address); 3929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadAddress(arg_reg_3, 3930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::isolate_address(isolate())); 39313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int argument_count = 3; 39323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 39343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(argument_count); 3935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction( 3936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::incremental_marking_record_write_function(isolate()), 3937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch argument_count); 3938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode()); 39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 39403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RecordWriteStub::CheckNeedsToInformIncrementalMarker( 39433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 39443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OnNoNeedToInformIncrementalMarker on_no_need, 39453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Mode mode) { 39463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label on_black; 39473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label need_incremental; 39483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label need_incremental_pop_object; 39493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(regs_.scratch0(), Immediate(~Page::kPageAlignmentMask)); 3951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ andp(regs_.scratch0(), regs_.object()); 3952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(regs_.scratch1(), 3953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(regs_.scratch0(), 3954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemoryChunk::kWriteBarrierCounterOffset)); 3955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(regs_.scratch1(), Immediate(1)); 3956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(regs_.scratch0(), 3957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemoryChunk::kWriteBarrierCounterOffset), 3958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch regs_.scratch1()); 3959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(negative, &need_incremental); 3960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 39613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Let's look at the color of the object: If it is not black we don't have 39623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // to inform the incremental marker. 39633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfBlack(regs_.object(), 39643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch0(), 39653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch1(), 39663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &on_black, 39673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::kNear); 39683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.Restore(masm); 39703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 3971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 39723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler::kReturnAtEnd); 39733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 39743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 39753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 39763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&on_black); 39783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the value from the slot. 3980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(regs_.scratch0(), Operand(regs_.address(), 0)); 39813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mode == INCREMENTAL_COMPACTION) { 39833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ensure_not_white; 39843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckPageFlag(regs_.scratch0(), // Contains value. 39863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch1(), // Scratch. 39873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemoryChunk::kEvacuationCandidateMask, 39883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch zero, 39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &ensure_not_white, 39903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::kNear); 39913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckPageFlag(regs_.object(), 39933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch1(), // Scratch. 39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemoryChunk::kSkipEvacuationSlotsRecordingMask, 39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch zero, 39963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &need_incremental); 39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&ensure_not_white); 39993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 40003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We need an extra register for this, so we push the object register 40023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // temporarily. 4003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(regs_.object()); 40043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ EnsureNotWhite(regs_.scratch0(), // The value. 40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.scratch1(), // Scratch. 40063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.object(), // Scratch. 40073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &need_incremental_pop_object, 40083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label::kNear); 4009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(regs_.object()); 40103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch regs_.Restore(masm); 40123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 4013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 40143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler::kReturnAtEnd); 40153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 40163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 40173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 40183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&need_incremental_pop_object); 4020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(regs_.object()); 40213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&need_incremental); 40233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fall through when we need to inform the incremental marker. 40253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 40263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { 40293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------- S t a t e ------------- 4030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rax : element value to store 4031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rcx : element index as smi 4032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[0] : return address 4033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[8] : array literal index in function 4034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[16] : array literal 4035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // clobbers rbx, rdx, rdi 40363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------------------------------- 40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label element_done; 40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label double_elements; 40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label smi_element; 40413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label slow_elements; 40423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fast_elements; 40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get array literal index, array literal and its map. 4045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); 4046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, args.GetArgumentOperand(1)); 4047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, args.GetArgumentOperand(0)); 4048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, FieldOperand(rbx, JSObject::kMapOffset)); 4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastElements(rdi, &double_elements); 40513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS 40533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rax, &smi_element); 4054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckFastSmiElements(rdi, &fast_elements); 40553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store into the array literal requires a elements transition. Call into 40573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the runtime. 40583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow_elements); 4060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(rdi); 4061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rbx); 4062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rcx); 4063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 4064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 4065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); 4066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 4067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushReturnAddressFrom(rdi); 40683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1); 40693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object. 40713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_elements); 40723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(kScratchRegister, rcx); 4073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rcx, FieldOperand(rbx, kScratchRegister, times_pointer_size, 40753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase::kHeaderSize)); 4076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rcx, 0), rax); 40773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier for the array store. 40783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(rbx, rcx, rax, 40793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 40803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 40813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 40823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 40833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or 4085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FAST_*_ELEMENTS, and value is Smi. 40863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&smi_element); 40873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(kScratchRegister, rcx); 4088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 4089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rbx, kScratchRegister, times_pointer_size, 40903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase::kHeaderSize), rax); 40913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 40923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. 40943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&double_elements); 40953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(r9, FieldOperand(rbx, JSObject::kElementsOffset)); 40973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(r11, rcx); 40983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ StoreNumberToDoubleElements(rax, 40993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r9, 41003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r11, 41013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch xmm0, 41023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &slow_elements); 41033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 41043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 41053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StubFailureTrampolineStub::Generate(MacroAssembler* masm) { 4108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CEntryStub ces(isolate(), 1, kSaveFPRegs); 4109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); 4110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parameter_count_offset = 4111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; 4112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, MemOperand(rbp, parameter_count_offset)); 4113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); 4114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(rcx); 4115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int additional_offset = 4116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function_mode() == JS_FUNCTION_STUB_MODE ? kPointerSize : 0; 4117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); 4118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(rcx); // Return to IC Miss stub, continuation still on stack. 4119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LoadICTrampolineStub::Generate(MacroAssembler* masm) { 4123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); 4124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VectorLoadStub stub(isolate(), state()); 4125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); 4126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { 4130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); 4131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VectorKeyedLoadStub stub(isolate()); 4132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); 4133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { 4137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (masm->isolate()->function_entry_hook() != NULL) { 4138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub stub(masm->isolate()); 4139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->CallStub(&stub); 4140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ProfileEntryHookStub::Generate(MacroAssembler* masm) { 4145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This stub can be called from essentially anywhere, so it needs to save 4146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // all volatile and callee-save registers. 4147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const size_t kNumSavedRegisters = 2; 4148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(arg_reg_1); 4149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(arg_reg_2); 4150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate the original stack pointer and store it in the second arg. 4152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(arg_reg_2, 4153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(rsp, kNumSavedRegisters * kRegisterSize + kPCOnStackSize)); 4154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate the function address to the first arg. 4156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(arg_reg_1, Operand(rsp, kNumSavedRegisters * kRegisterSize)); 4157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(arg_reg_1, Immediate(Assembler::kShortCallInstructionLength)); 4158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the remainder of the volatile registers. 4160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->PushCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2); 4161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the entry hook function. 4163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rax, FUNCTION_ADDR(isolate()->function_entry_hook()), 4164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::RelocInfoNone()); 4165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 4167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kArgumentCount = 2; 4169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(kArgumentCount); 4170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction(rax, kArgumentCount); 4171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore volatile regs. 4173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->PopCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2); 4174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(arg_reg_2); 4175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(arg_reg_1); 4176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T> 4182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CreateArrayDispatch(MacroAssembler* masm, 4183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteOverrideMode mode) { 4184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode == DISABLE_ALLOCATION_SITES) { 4185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T stub(masm->isolate(), GetInitialFastElementsKind(), mode); 4186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 4187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (mode == DONT_OVERRIDE) { 4188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int last_index = GetSequenceIndexFromFastElementsKind( 4189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TERMINAL_FAST_ELEMENTS_KIND); 4190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i <= last_index; ++i) { 4191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label next; 4192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rdx, Immediate(kind)); 4194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &next); 4195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T stub(masm->isolate(), kind); 4196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 4197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&next); 4198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we reached this point there is a problem. 4201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kUnexpectedElementsKindInArrayConstructor); 4202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 4204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CreateArrayDispatchOneArgument(MacroAssembler* masm, 4209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteOverrideMode mode) { 4210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rbx - allocation site (if mode != DISABLE_ALLOCATION_SITES) 4211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdx - kind (if mode != DISABLE_ALLOCATION_SITES) 4212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rax - number of arguments 4213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rdi - constructor? 4214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[0] - return address 4215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rsp[8] - last argument 4216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> undefined_sentinel( 4217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->undefined_value(), 4218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()); 4219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label normal_sequence; 4221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode == DONT_OVERRIDE) { 4222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(FAST_SMI_ELEMENTS == 0); 4223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(FAST_HOLEY_SMI_ELEMENTS == 1); 4224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(FAST_ELEMENTS == 2); 4225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(FAST_HOLEY_ELEMENTS == 3); 4226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(FAST_DOUBLE_ELEMENTS == 4); 4227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(FAST_HOLEY_DOUBLE_ELEMENTS == 5); 4228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is the low bit set? If so, we are holey and that is good. 4230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testb(rdx, Immediate(1)); 4231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &normal_sequence); 4232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // look at the first argument 4235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); 4236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, args.GetArgumentOperand(0)); 4237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rcx, rcx); 4238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &normal_sequence); 4239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode == DISABLE_ALLOCATION_SITES) { 4241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind initial = GetInitialFastElementsKind(); 4242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind holey_initial = GetHoleyElementsKind(initial); 4243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArraySingleArgumentConstructorStub stub_holey(masm->isolate(), 4245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holey_initial, 4246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISABLE_ALLOCATION_SITES); 4247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub_holey); 4248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&normal_sequence); 4250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArraySingleArgumentConstructorStub stub(masm->isolate(), 4251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch initial, 4252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISABLE_ALLOCATION_SITES); 4253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 4254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (mode == DONT_OVERRIDE) { 4255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We are going to create a holey array, but our kind is non-holey. 4256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fix kind and retry (only if we have an allocation site in the slot). 4257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ incl(rdx); 4258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 4260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> allocation_site_map = 4261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->factory()->allocation_site_map(); 4262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(FieldOperand(rbx, 0), allocation_site_map); 4263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kExpectedAllocationSite); 4264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the resulting elements kind in type info. We can't just store r3 4267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in the AllocationSite::transition_info field because elements kind is 4268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // restricted to a portion of the field...upper bits need to be left alone. 4269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 4270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiAddConstant(FieldOperand(rbx, AllocationSite::kTransitionInfoOffset), 4271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(kFastElementsKindPackedToHoley)); 4272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&normal_sequence); 4274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int last_index = GetSequenceIndexFromFastElementsKind( 4275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TERMINAL_FAST_ELEMENTS_KIND); 4276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i <= last_index; ++i) { 4277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label next; 4278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rdx, Immediate(kind)); 4280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &next); 4281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArraySingleArgumentConstructorStub stub(masm->isolate(), kind); 4282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 4283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&next); 4284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we reached this point there is a problem. 4287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kUnexpectedElementsKindInArrayConstructor); 4288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 4290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T> 4295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { 4296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int to_index = GetSequenceIndexFromFastElementsKind( 4297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TERMINAL_FAST_ELEMENTS_KIND); 4298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i <= to_index; ++i) { 4299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T stub(isolate, kind); 4301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stub.GetCode(); 4302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { 4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T stub1(isolate, kind, DISABLE_ALLOCATION_SITES); 4304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stub1.GetCode(); 4305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { 4311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( 4312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate); 4313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( 4314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate); 4315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( 4316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate); 4317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( 4321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate) { 4322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS }; 4323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < 2; i++) { 4324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For internal arrays we only need a few things 4325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]); 4326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stubh1.GetCode(); 4327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]); 4328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stubh2.GetCode(); 4329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); 4330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stubh3.GetCode(); 4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayConstructorStub::GenerateDispatchToArrayStub( 4336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, 4337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteOverrideMode mode) { 4338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (argument_count() == ANY) { 4339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_zero_case, not_one_case; 4340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rax, rax); 4341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, ¬_zero_case); 4342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 4343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_zero_case); 4345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rax, Immediate(1)); 4346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(greater, ¬_one_case); 4347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateArrayDispatchOneArgument(masm, mode); 4348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_one_case); 4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 4351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (argument_count() == NONE) { 4352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 4353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (argument_count() == ONE) { 4354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateArrayDispatchOneArgument(masm, mode); 4355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (argument_count() == MORE_THAN_ONE) { 4356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 4357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 4359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayConstructorStub::Generate(MacroAssembler* masm) { 4364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rax : argc 4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rbx : AllocationSite or undefined 4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rdi : constructor 4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[0] : return address 4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[8] : last argument 4370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The array construct code is only set for the global and natives 4373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // builtin Array functions which always have maps. 4374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initial map for the builtin Array function should be a map. 4376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 4377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Will both indicate a NULL and a Smi. 4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 4379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); 4380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); 4381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(rcx, MAP_TYPE, rcx); 4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(equal, kUnexpectedInitialMapForArrayFunction); 4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We should either have undefined in rbx or a valid AllocationSite 4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertUndefinedOrAllocationSite(rbx); 4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_info; 4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the feedback vector is the undefined value call an array constructor 4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // that doesn't use AllocationSites. 4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &no_info); 4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only look at the lower 16 bits of the transition info. 4395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, FieldOperand(rbx, AllocationSite::kTransitionInfoOffset)); 4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rdx, rdx); 4397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 4398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ andp(rdx, Immediate(AllocationSite::ElementsKindBits::kMask)); 4399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); 4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_info); 4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); 4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArrayConstructorStub::GenerateCase( 4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, ElementsKind kind) { 4408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_zero_case, not_one_case; 4409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label normal_sequence; 4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rax, rax); 4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, ¬_zero_case); 4413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InternalArrayNoArgumentConstructorStub stub0(isolate(), kind); 4414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub0); 4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_zero_case); 4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rax, Immediate(1)); 4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(greater, ¬_one_case); 4419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsFastPackedElementsKind(kind)) { 4421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We might need to create a holey array 4422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // look at the first argument 4423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); 4424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, args.GetArgumentOperand(0)); 4425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rcx, rcx); 4426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &normal_sequence); 4427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InternalArraySingleArgumentConstructorStub 4429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stub1_holey(isolate(), GetHoleyElementsKind(kind)); 4430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub1_holey); 4431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&normal_sequence); 4434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InternalArraySingleArgumentConstructorStub stub1(isolate(), kind); 4435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub1); 4436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_one_case); 4438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InternalArrayNArgumentsConstructorStub stubN(isolate(), kind); 4439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stubN); 4440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArrayConstructorStub::Generate(MacroAssembler* masm) { 4444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 4445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rax : argc 4446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rdi : constructor 4447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[0] : return address 4448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[8] : last argument 4449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 4450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 4452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The array construct code is only set for the global and natives 4453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // builtin Array functions which always have maps. 4454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initial map for the builtin Array function should be a map. 4456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 4457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Will both indicate a NULL and a Smi. 4458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 4459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); 4460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); 4461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(rcx, MAP_TYPE, rcx); 4462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(equal, kUnexpectedInitialMapForArrayFunction); 4463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Figure out the right elements kind 4466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 4467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the map's "bit field 2" into |result|. We only need the first byte, 4469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // but the following masking takes care of that anyway. 4470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbp(rcx, FieldOperand(rcx, Map::kBitField2Offset)); 4471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Retrieve elements_kind from bit field 2. 4472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ DecodeField<Map::ElementsKindBits>(rcx); 4473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 4475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 4476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rcx, Immediate(FAST_ELEMENTS)); 4477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &done); 4478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rcx, Immediate(FAST_HOLEY_ELEMENTS)); 4479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, 4480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kInvalidElementsKindForInternalArrayOrInternalPackedArray); 4481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 4482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label fast_elements_case; 4485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rcx, Immediate(FAST_ELEMENTS)); 4486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &fast_elements_case); 4487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateCase(masm, FAST_HOLEY_ELEMENTS); 4488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&fast_elements_case); 4490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateCase(masm, FAST_ELEMENTS); 4491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallApiFunctionStub::Generate(MacroAssembler* masm) { 4495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 4496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rax : callee 4497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rbx : call_data 4498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rcx : holder 4499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rdx : api_function_address 4500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsi : context 4501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- 4502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[0] : return address 4503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[8] : last argument 4504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- ... 4505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[argc * 8] : first argument 4506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[(argc + 1) * 8] : receiver 4507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 4508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register callee = rax; 4510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register call_data = rbx; 4511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder = rcx; 4512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register api_function_address = rdx; 4513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register return_address = rdi; 4514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register context = rsi; 4515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int argc = this->argc(); 4517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_store = this->is_store(); 4518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool call_data_undefined = this->call_data_undefined(); 4519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef FunctionCallbackArguments FCA; 4521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kContextSaveIndex == 6); 4523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kCalleeIndex == 5); 4524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kDataIndex == 4); 4525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kReturnValueOffset == 3); 4526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 4527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kIsolateIndex == 1); 4528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kHolderIndex == 0); 4529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kArgsLength == 7); 4530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(return_address); 4532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context save 4534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(context); 4535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // load context from callee 4536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(context, FieldOperand(callee, JSFunction::kContextOffset)); 4537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // callee 4539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(callee); 4540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // call data 4542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(call_data); 4543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = call_data; 4544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!call_data_undefined) { 4545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 4546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // return value 4548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch); 4549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // return value default 4550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch); 4551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // isolate 4552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(scratch, 4553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::isolate_address(isolate())); 4554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch); 4555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // holder 4556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(holder); 4557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, rsp); 4559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push return address back on stack. 4560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushReturnAddressFrom(return_address); 4561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate the v8::Arguments structure in the arguments' space since 4563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // it's not controlled by GC. 4564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kApiStackSpace = 4; 4565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallApiFunction(kApiStackSpace); 4567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FunctionCallbackInfo::implicit_args_. 4569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(StackSpaceOperand(0), scratch); 4570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(scratch, Immediate((argc + FCA::kArgsLength - 1) * kPointerSize)); 4571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(StackSpaceOperand(1), scratch); // FunctionCallbackInfo::values_. 4572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(StackSpaceOperand(2), argc); // FunctionCallbackInfo::length_. 4573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FunctionCallbackInfo::is_construct_call_. 4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Set(StackSpaceOperand(3), 0); 4575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(__MINGW64__) || defined(_WIN64) 4577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register arguments_arg = rcx; 4578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register callback_arg = rdx; 4579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 4580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register arguments_arg = rdi; 4581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register callback_arg = rsi; 4582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 4583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's okay if api_function_address == callback_arg 4585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // but not arguments_arg 4586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!api_function_address.is(arguments_arg)); 4587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // v8::InvocationCallback's argument. 4589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(arguments_arg, StackSpaceOperand(0)); 4590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference thunk_ref = 4592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::invoke_function_callback(isolate()); 4593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Accessor for FunctionCallbackInfo and first js arg. 4595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength + 1, 4596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ARGUMENTS_DONT_CONTAIN_RECEIVER); 4597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand context_restore_operand = args_from_rbp.GetArgumentOperand( 4598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FCA::kArgsLength - FCA::kContextSaveIndex); 4599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stores return the first js argument 4600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand return_value_operand = args_from_rbp.GetArgumentOperand( 4601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch is_store ? 0 : FCA::kArgsLength - FCA::kReturnValueOffset); 4602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallApiFunctionAndReturn( 4603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch api_function_address, 4604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch thunk_ref, 4605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch callback_arg, 4606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch argc + FCA::kArgsLength + 1, 4607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return_value_operand, 4608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &context_restore_operand); 4609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallApiGetterStub::Generate(MacroAssembler* masm) { 4613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 4614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[0] : return address 4615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[8] : name 4616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[16 - kArgsLength*8] : PropertyCallbackArguments object 4617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- ... 4618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- r8 : api_function_address 4619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 4620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(__MINGW64__) || defined(_WIN64) 4622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register getter_arg = r8; 4623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register accessor_info_arg = rdx; 4624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name_arg = rcx; 4625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 4626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register getter_arg = rdx; 4627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register accessor_info_arg = rsi; 4628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name_arg = rdi; 4629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 4630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register api_function_address = ApiGetterDescriptor::function_address(); 4631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(api_function_address.is(r8)); 4632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = rax; 4633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // v8::Arguments::values_ and handler for name. 4635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1; 4636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate v8::AccessorInfo in non-GCed stack space. 4638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kArgStackSpace = 1; 4639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(name_arg, Operand(rsp, kPCOnStackSize)); 4641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallApiFunction(kArgStackSpace); 4643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(scratch, Operand(name_arg, 1 * kPointerSize)); 4644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // v8::PropertyAccessorInfo::args_. 4646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(StackSpaceOperand(0), scratch); 4647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The context register (rsi) has been saved in PrepareCallApiFunction and 4649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // could be used to pass arguments. 4650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(accessor_info_arg, StackSpaceOperand(0)); 4651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference thunk_ref = 4653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::invoke_accessor_getter_callback(isolate()); 4654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's okay if api_function_address == getter_arg 4656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // but not accessor_info_arg or name_arg 4657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!api_function_address.is(accessor_info_arg) && 4658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !api_function_address.is(name_arg)); 4659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The name handler is counted as an argument. 4661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength); 4662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand return_value_operand = args.GetArgumentOperand( 4663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyCallbackArguments::kArgsLength - 1 - 4664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyCallbackArguments::kReturnValueOffset); 4665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallApiFunctionAndReturn(api_function_address, 4666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch thunk_ref, 4667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch getter_arg, 4668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kStackSpace, 4669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return_value_operand, 4670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NULL); 4671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 467480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#undef __ 467580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 467680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} } // namespace v8::internal 467780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 467880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif // V8_TARGET_ARCH_X64 4679