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#if V8_TARGET_ARCH_X64 680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 73b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/api-arguments.h" 83b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/bootstrapper.h" 962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/code-stubs.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 1162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/counters.h" 1262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/double.h" 1362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/heap/heap-inl.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/handler-compiler.h" 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ic/stub-cache.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate.h" 1862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h" 1962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects/regexp-match-info.h" 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/jsregexp.h" 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/regexp-macro-assembler.h" 22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h" 2362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/x64/code-stubs-x64.h" // Cannot be the first include. 2580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 2880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define __ ACCESS_MASM(masm) 3080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) { 3213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ popq(rcx); 3313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ movq(MemOperand(rsp, rax, times_8, 0), rdi); 3413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ pushq(rdi); 3513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ pushq(rbx); 3613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ pushq(rcx); 3713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ addq(rax, Immediate(3)); 3813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ TailCallRuntime(Runtime::kNewArray); 3980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 4080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm, 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference miss) { 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the static counter each time a new code stub is generated. 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->counters()->code_stubs()->Increment(); 4580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor(); 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int param_count = descriptor.GetRegisterParameterCount(); 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime system in a fresh internal frame. 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(param_count == 0 || 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch rax.is(descriptor.GetRegisterParameter(param_count - 1))); 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push arguments 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < param_count; ++i) { 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(descriptor.GetRegisterParameter(i)); 5669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallExternalReference(miss, param_count); 5869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 5980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 6169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 6280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 6369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushCallerSaved(save_doubles() ? kSaveFPRegs : kDontSaveFPRegs); 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int argument_count = 1; 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(argument_count); 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadAddress(arg_reg_1, 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::isolate_address(isolate())); 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction( 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::store_buffer_overflow_function(isolate()), 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch argument_count); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopCallerSaved(save_doubles() ? kSaveFPRegs : kDontSaveFPRegs); 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass FloatingPointHelper : public AllStatic { 8180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public: 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum ConvertUndefined { 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CONVERT_UNDEFINED_TO_ZERO, 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BAILOUT_ON_UNDEFINED 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 8680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. 8780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If the operands are not both numbers, jump to not_numbers. 8880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Leaves rdx and rax unchanged. SmiOperands assumes both are smis. 8980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // NumberOperands assumes both are smis or heap numbers. 9080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen static void LoadSSE2UnknownOperands(MacroAssembler* masm, 9180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* not_numbers); 928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}; 9380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 9480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid DoubleToIStub::Generate(MacroAssembler* masm) { 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg = this->source(); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register final_result_reg = this->destination(); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_truncating()); 993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label check_negative, process_64_bits, done; 101086aeeaae12517475c22695a200be45495516549Ben Murdoch 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int double_offset = offset(); 1031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Account for return address and saved regs if input is rsp. 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (input_reg.is(rsp)) double_offset += 3 * kRegisterSize; 106086aeeaae12517475c22695a200be45495516549Ben Murdoch 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand mantissa_operand(MemOperand(input_reg, double_offset)); 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand exponent_operand(MemOperand(input_reg, 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double_offset + kDoubleSize / 2)); 1101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1; 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch_candidates[3] = { rbx, rdx, rdi }; 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < 3; i++) { 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch1 = scratch_candidates[i]; 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!final_result_reg.is(scratch1) && !input_reg.is(scratch1)) break; 1168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Since we must use rcx for shifts below, use some other register (rax) 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to calculate the result if ecx is the requested return register. 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_reg = final_result_reg.is(rcx) ? rax : final_result_reg; 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save ecx if it isn't the return register and therefore volatile, or if it 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is the return register, then save the temp register we use in its stead 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for the result. 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register save_reg = final_result_reg.is(rcx) ? rax : rcx; 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(scratch1); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(save_reg); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool stash_exponent_copy = !input_reg.is(rsp); 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movl(scratch1, mantissa_operand); 13013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Movsd(kScratchDoubleReg, mantissa_operand); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movl(rcx, exponent_operand); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stash_exponent_copy) __ pushq(rcx); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ andl(rcx, Immediate(HeapNumber::kExponentMask)); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shrl(rcx, Immediate(HeapNumber::kExponentShift)); 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leal(result_reg, MemOperand(rcx, -HeapNumber::kExponentBias)); 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(result_reg, Immediate(HeapNumber::kMantissaBits)); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, &process_64_bits); 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result is entirely in lower 32-bits of mantissa 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize; 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subl(rcx, Immediate(delta)); 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xorl(result_reg, result_reg); 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(rcx, Immediate(31)); 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, &done); 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shll_cl(scratch1); 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&check_negative); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&process_64_bits); 15013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Cvttsd2siq(result_reg, kScratchDoubleReg); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the double was negative, negate the integer result. 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_negative); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movl(result_reg, scratch1); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ negl(result_reg); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stash_exponent_copy) { 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(MemOperand(rsp, 0), Immediate(0)); 1598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(exponent_operand, Immediate(0)); 1611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmovl(greater, result_reg, scratch1); 16380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore registers 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stash_exponent_copy) { 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(kDoubleSize)); 168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!final_result_reg.is(result_reg)) { 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(final_result_reg.is(rcx)); 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movl(final_result_reg, result_reg); 172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(save_reg); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(scratch1); 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 17680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 17780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 17880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 17980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, 18080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* not_numbers) { 18180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done; 18280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load operand in rdx into xmm0, or branch to not_numbers. 18380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex); 18480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfSmi(rdx, &load_smi_rdx); 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(FieldOperand(rdx, HeapObject::kMapOffset), rcx); 18680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, not_numbers); // Argument in rdx is not a number. 187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); 18880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load operand in rax into xmm1, or branch to not_numbers. 18980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfSmi(rax, &load_smi_rax); 19080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 19180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&load_nonsmi_rax); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(FieldOperand(rax, HeapObject::kMapOffset), rcx); 19380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, not_numbers); 194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); 19580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&done); 19680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 19780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&load_smi_rdx); 19880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiToInteger32(kScratchRegister, rdx); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtlsi2sd(xmm0, kScratchRegister); 20080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfNotSmi(rax, &load_nonsmi_rax); 20180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 20280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&load_smi_rax); 20380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiToInteger32(kScratchRegister, rax); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtlsi2sd(xmm1, kScratchRegister); 20580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 20680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 20780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 20880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MathPowStub::Generate(MacroAssembler* masm) { 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register exponent = MathPowTaggedDescriptor::exponent(); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(exponent.is(rdx)); 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Register scratch = rcx; 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const XMMRegister double_result = xmm3; 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const XMMRegister double_base = xmm2; 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const XMMRegister double_exponent = xmm1; 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const XMMRegister double_scratch = xmm4; 217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label call_runtime, done, exponent_not_smi, int_exponent; 219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save 1 in double_result - we need this several times later on. 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, Immediate(1)); 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtlsi2sd(double_result, scratch); 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (exponent_type() == TAGGED) { 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(exponent, exponent); 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&int_exponent); 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&exponent_not_smi); 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (exponent_type() != INTEGER) { 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label fast_power, try_arithmetic_simplification; 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Detect integer exponents stored as double. 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ DoubleToI(exponent, double_exponent, double_scratch, 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification, 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &try_arithmetic_simplification, 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &try_arithmetic_simplification); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&int_exponent); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&try_arithmetic_simplification); 243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Cvttsd2si(exponent, double_exponent); 2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Skip to runtime if possibly NaN (indicated by the indefinite integer). 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(exponent, Immediate(0x1)); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(overflow, &call_runtime); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Using FPU instructions to calculate power. 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fast_power_failed; 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_power); 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fnclex(); // Clear flags to catch exceptions later. 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Transfer (B)ase and (E)xponent onto the FPU register stack. 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rsp, Immediate(kDoubleSize)); 254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Movsd(Operand(rsp, 0), double_exponent); 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fld_d(Operand(rsp, 0)); // E 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Movsd(Operand(rsp, 0), double_base); 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fld_d(Operand(rsp, 0)); // B, E 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Exponent is in st(1) and base is in st(0) 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // B ^ E = (2^(E * log2(B)) - 1) + 1 = (2^X - 1) + 1 for X = E * log2(B) 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FYL2X calculates st(1) * log2(st(0)) 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fyl2x(); // X 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fld(0); // X, X 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ frndint(); // rnd(X), X 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fsub(1); // rnd(X), X-rnd(X) 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fxch(1); // X - rnd(X), rnd(X) 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // F2XM1 calculates 2^st(0) - 1 for -1 < st(0) < 1 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ f2xm1(); // 2^(X-rnd(X)) - 1, rnd(X) 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fld1(); // 1, 2^(X-rnd(X)) - 1, rnd(X) 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ faddp(1); // 2^(X-rnd(X)), rnd(X) 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FSCALE calculates st(0) * 2^st(1) 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fscale(); // 2^X, rnd(X) 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fstp(1); 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Bail out to runtime in case of exceptions in the status word. 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fnstsw_ax(); 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testb(rax, Immediate(0x5F)); // Check for all but precision exception. 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_zero, &fast_power_failed, Label::kNear); 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fstp_d(Operand(rsp, 0)); 279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Movsd(double_result, Operand(rsp, 0)); 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(kDoubleSize)); 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_power_failed); 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fninit(); 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(kDoubleSize)); 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&call_runtime); 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 28885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calculate power with integer exponent. 2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&int_exponent); 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const XMMRegister double_scratch2 = double_exponent; 2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Back up exponent as we need to check if exponent is negative later. 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, exponent); // Back up exponent. 294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Movsd(double_scratch, double_base); // Back up base. 295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Movsd(double_scratch2, double_result); // Load double_exponent with 1. 296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Get absolute value of exponent. 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_neg, while_true, while_false; 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testl(scratch, scratch); 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(positive, &no_neg, Label::kNear); 3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ negl(scratch); 302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&no_neg); 303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &while_false, Label::kNear); 3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ shrl(scratch, Immediate(1)); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Above condition means CF==0 && ZF==0. This means that the 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit that has been shifted out is 0 and the result is not 0. 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, &while_true, Label::kNear); 309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Movsd(double_result, double_scratch); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &while_false, Label::kNear); 311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&while_true); 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shrl(scratch, Immediate(1)); 314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mulsd(double_scratch, double_scratch); 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, &while_true, Label::kNear); 316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mulsd(double_result, double_scratch); 3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_zero, &while_true); 31885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&while_false); 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the exponent is negative, return 1/result. 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testl(exponent, exponent); 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(greater, &done); 323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Divsd(double_scratch2, double_result); 324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Movsd(double_result, double_scratch2); 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test whether result is zero. Bail out to check for subnormal result. 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. 327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Xorpd(double_scratch2, double_scratch2); 328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ucomisd(double_scratch2, double_result); 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // double_exponent aliased as double_scratch2 has already been overwritten 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and may not have contained the exponent value in the first place when the 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // input was a smi. We reset it with exponent value before bailing out. 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &done); 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtlsi2sd(double_exponent, exponent); 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Returning or bailing out. 336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&call_runtime); 337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Move base to the correct argument register. Exponent is already in xmm1. 338f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Movsd(xmm0, double_base); 339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(double_exponent.is(xmm1)); 340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 341f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 342f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PrepareCallCFunction(2); 343f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CallCFunction(ExternalReference::power_double_double_function(isolate()), 344f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2); 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 346f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Return value is in xmm0. 347f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Movsd(double_result, xmm0); 348f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&done); 350f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ ret(0); 351e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 352e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 353109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid RegExpExecStub::Generate(MacroAssembler* masm) { 354109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Just jump directly to runtime if native RegExp is not selected at compile 355109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // time or if regexp entry in generated code is turned off runtime switch or 356109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // at compilation. 357109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#ifdef V8_INTERPRETED_REGEXP 358109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallRuntime(Runtime::kRegExpExec); 359109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else // V8_INTERPRETED_REGEXP 3603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 361109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Stack frame on entry. 362109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rsp[0] : return address 363109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rsp[8] : last_match_info (expected JSArray) 364109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rsp[16] : previous index 365109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rsp[24] : subject string 366109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rsp[32] : JSRegExp object 3673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 368109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch enum RegExpExecStubArgumentIndices { 369109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch JS_REG_EXP_OBJECT_ARGUMENT_INDEX, 370109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch SUBJECT_STRING_ARGUMENT_INDEX, 371109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PREVIOUS_INDEX_ARGUMENT_INDEX, 372109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch LAST_MATCH_INFO_ARGUMENT_INDEX, 373109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch REG_EXP_EXEC_ARGUMENT_COUNT 374109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch }; 3753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 376109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch StackArgumentsAccessor args(rsp, REG_EXP_EXEC_ARGUMENT_COUNT, 377109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ARGUMENTS_DONT_CONTAIN_RECEIVER); 378109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label runtime; 379109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Ensure that a RegExp stack is allocated. 380109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference address_of_regexp_stack_memory_address = 381109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference::address_of_regexp_stack_memory_address(isolate()); 382109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference address_of_regexp_stack_memory_size = 383109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ExternalReference::address_of_regexp_stack_memory_size(isolate()); 384109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Load(kScratchRegister, address_of_regexp_stack_memory_size); 385109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ testp(kScratchRegister, kScratchRegister); 386109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(zero, &runtime); 3873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 388109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check that the first argument is a JSRegExp object. 389109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX)); 390109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(rax, &runtime); 391109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); 392109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &runtime); 3933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 394109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check that the RegExp has been compiled (data contains a fixed array). 395109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rax, FieldOperand(rax, JSRegExp::kDataOffset)); 396109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 397109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Condition is_smi = masm->CheckSmi(rax); 398109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Check(NegateCondition(is_smi), 399109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kUnexpectedTypeForRegExpDataFixedArrayExpected); 400109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister); 401109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected); 402109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 4033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 404109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rax: RegExp data (FixedArray) 405109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 406109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToInteger32(rbx, FieldOperand(rax, JSRegExp::kDataTagOffset)); 407109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP)); 408109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &runtime); 4093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 410109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rax: RegExp data (FixedArray) 411109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check that the number of captures fit in the static offsets vector buffer. 412109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToInteger32(rdx, 413109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset)); 414109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check (number_of_captures + 1) * 2 <= offsets vector size 415109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Or number_of_captures <= offsets vector size / 2 - 1 416109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); 417109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); 418109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(above, &runtime); 4193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 420109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reset offset for possibly sliced string. 421109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Set(r14, 0); 422109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); 423109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(rdi, &runtime); 424109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(r15, rdi); // Make a copy of the original subject string. 425109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rax: RegExp data (FixedArray) 426109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rdi: subject string 427109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // r15: subject string 428109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Handle subject string according to its encoding and representation: 429109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (1) Sequential two byte? If yes, go to (9). 430109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (2) Sequential one byte? If yes, go to (5). 431109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (3) Sequential or cons? If not, go to (6). 432109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (4) Cons string. If the string is flat, replace subject with first string 433109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // and go to (1). Otherwise bail out to runtime. 434109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (5) One byte sequential. Load regexp code for one byte. 435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (E) Carry on. 436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch /// [...] 4373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Deferred code at the end of the stub: 439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (6) Long external string? If not, go to (10). 440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (7) External string. Make it, offset-wise, look like a sequential string. 441109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (8) Is the external string one byte? If yes, go to (5). 442109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (9) Two byte sequential. Load regexp code for two byte. Go to (E). 443109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (10) Short external string or not a string? If yes, bail out to runtime. 44462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // (11) Sliced or thin string. Replace subject with parent. Go to (1). 4453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 446109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */, 447109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch external_string /* 7 */, check_underlying /* 1 */, 448109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */; 4493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 450109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&check_underlying); 451109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 452109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 4533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 454109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (1) Sequential two byte? If yes, go to (9). 455109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andb(rbx, Immediate(kIsNotStringMask | 456109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kStringRepresentationMask | 457109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kStringEncodingMask | 458109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kShortExternalStringMask)); 459109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); 460109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(zero, &seq_two_byte_string); // Go to (9). 4613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 462109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (2) Sequential one byte? If yes, go to (5). 463109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Any other sequential string must be one byte. 464109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andb(rbx, Immediate(kIsNotStringMask | 465109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kStringRepresentationMask | 466109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kShortExternalStringMask)); 467109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5). 4683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 469109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (3) Sequential or cons? If not, go to (6). 470109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We check whether the subject string is a cons, since sequential strings 471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // have already been covered. 472109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kConsStringTag < kExternalStringTag); 473109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 47462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(kThinStringTag > kExternalStringTag); 475109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 476109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 477109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpp(rbx, Immediate(kExternalStringTag)); 478109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(greater_equal, ¬_seq_nor_cons); // Go to (6). 4793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 480109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (4) Cons string. Check that it's flat. 481109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Replace subject with first string and reload instance type. 482109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), 483109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Heap::kempty_stringRootIndex); 484109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &runtime); 485109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); 486109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&check_underlying); 48780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 488109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (5) One byte sequential. Load regexp code for one byte. 489f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&seq_one_byte_string); 490f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rax: RegExp data (FixedArray) 491f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset)); 492f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Set(rcx, 1); // Type is one byte. 4938389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 494f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // (E) Carry on. String handling is done. 495f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&check_code); 496f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r11: irregexp code 497f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that the irregexp code has been generated for the actual string 498f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // encoding. If it has, the field contains a code object otherwise it contains 499f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // smi (code flushing support) 500f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfSmi(r11, &runtime); 5018389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 502f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdi: sequential subject string (or look-alike, external string) 503f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r15: original subject string 504f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rcx: encoding of subject string (1 if one_byte, 0 if two_byte); 505f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r11: code 506f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Load used arguments before starting to push arguments for call to native 507f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // RegExp code to avoid handling changing stack height. 508f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // We have to use r15 instead of rdi to load the length because rdi might 509f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // have been only made to look like a sequential string when it actually 510f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // is an external string. 511f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rbx, args.GetArgumentOperand(PREVIOUS_INDEX_ARGUMENT_INDEX)); 512f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotSmi(rbx, &runtime); 513f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset)); 514f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(above_equal, &runtime); 515f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger64(rbx, rbx); 516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 517f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdi: subject string 518f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rbx: previous index 519f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rcx: encoding of subject string (1 if one_byte 0 if two_byte); 520f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r11: code 521f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // All checks done. Now push arguments for native regexp code. 522f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Counters* counters = isolate()->counters(); 523f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ IncrementCounter(counters->regexp_entry_native(), 1); 524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 525f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Isolates: note we add an additional parameter here (isolate pointer). 526f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch static const int kRegExpExecuteArguments = 9; 527f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch int argument_slots_on_stack = 528f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); 529f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ EnterApiExitFrame(argument_slots_on_stack); 530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 531f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Argument 9: Pass current isolate address. 532f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadAddress(kScratchRegister, 533f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference::isolate_address(isolate())); 534f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kRegisterSize), 535f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch kScratchRegister); 536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 537f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Argument 8: Indicate that this is a direct call from JavaScript. 538f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kRegisterSize), 539f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Immediate(1)); 5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 541f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Argument 7: Start (high end) of backtracking stack memory area. 542f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(kScratchRegister, address_of_regexp_stack_memory_address); 543f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(r9, Operand(kScratchRegister, 0)); 544f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(kScratchRegister, address_of_regexp_stack_memory_size); 545f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ addp(r9, Operand(kScratchRegister, 0)); 546f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kRegisterSize), r9); 5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 548f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Argument 6: Set the number of capture registers to zero to force global 549f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // regexps to behave as non-global. This does not affect non-global regexps. 550f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Argument 6 is passed in r9 on Linux and on the stack on Windows. 551f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#ifdef _WIN64 552f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kRegisterSize), 553f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Immediate(0)); 554f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#else 555f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Set(r9, 0); 556f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#endif 557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 558f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Argument 5: static offsets vector buffer. 559f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadAddress( 560f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch r8, ExternalReference::address_of_static_offsets_vector(isolate())); 561f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Argument 5 passed in r8 on Linux and on the stack on Windows. 562f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#ifdef _WIN64 563f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movq(Operand(rsp, (argument_slots_on_stack - 5) * kRegisterSize), r8); 564f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#endif 565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 566f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdi: subject string 567f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rbx: previous index 568f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rcx: encoding of subject string (1 if one_byte 0 if two_byte); 569f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r11: code 570f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r14: slice offset 571f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r15: original subject string 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 573f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Argument 2: Previous index. 574f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(arg_reg_2, rbx); 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 576f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Argument 4: End of string data 577f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Argument 3: Start of string data 578f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label setup_two_byte, setup_rest, got_length, length_not_from_slice; 579f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Prepare start and end index of the input. 580f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Load the length from the original sliced string if that is the case. 581f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ addp(rbx, r14); 582f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(arg_reg_3, FieldOperand(r15, String::kLengthOffset)); 583f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ addp(r14, arg_reg_3); // Using arg3 as scratch. 5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 585f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rbx: start index of the input 586f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r14: end index of the input 587f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r15: original subject string 588f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. 589f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(zero, &setup_two_byte, Label::kNear); 590f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(arg_reg_4, 591f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(rdi, r14, times_1, SeqOneByteString::kHeaderSize)); 592f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(arg_reg_3, 593f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(rdi, rbx, times_1, SeqOneByteString::kHeaderSize)); 594f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&setup_rest, Label::kNear); 595f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&setup_two_byte); 596f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(arg_reg_4, 597f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize)); 598f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(arg_reg_3, 599f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); 600f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&setup_rest); 6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 602f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Argument 1: Original subject string. 603f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // The original subject is in the previous stack frame. Therefore we have to 604f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // use rbp, which points exactly to one pointer size below the previous rsp. 605f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // (Because creating a new stack frame pushes the previous rbp onto the stack 606f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // and thereby moves up rsp by one kPointerSize.) 607f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(arg_reg_1, r15); 6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 609f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Locate the code entry and call it. 610f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ addp(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); 611f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ call(r11); 61280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 613f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LeaveApiExitFrame(true); 61480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 615f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check the result. 616f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label success; 617f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label exception; 618f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpl(rax, Immediate(1)); 619f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // We expect exactly one result since we force the called regexp to behave 620f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // as non-global. 621f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &success, Label::kNear); 622f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); 623f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &exception); 624f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); 625f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If none of the above, it can only be retry. 626f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Handle that in the runtime system. 627f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &runtime); 628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 629f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // For failure return null. 630f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadRoot(rax, Heap::kNullValueRootIndex); 631f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize); 63280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 633f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Load RegExp data. 634f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&success); 635f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX)); 636f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); 637f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(rax, 638f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); 639f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Calculate number of capture registers (number_of_captures + 1) * 2. 640f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leal(rdx, Operand(rax, rax, times_1, 2)); 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 642f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdx: Number of capture registers 643c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check that the last match info is a FixedArray. 644c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ movp(rbx, args.GetArgumentOperand(LAST_MATCH_INFO_ARGUMENT_INDEX)); 645c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ JumpIfSmi(rbx, &runtime); 646f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check that the object has fast elements. 647f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rax, FieldOperand(rbx, HeapObject::kMapOffset)); 648f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex); 649f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &runtime); 650f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that the last match info has space for the capture registers and the 651f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // additional information. Ensure no overflow in add. 652f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); 653f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); 654c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ subl(rax, Immediate(RegExpMatchInfo::kLastMatchOverhead)); 655f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpl(rdx, rax); 656f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(greater, &runtime); 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 658c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // rbx: last_match_info (FixedArray) 659f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdx: number of capture registers 660f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Store the capture count. 661f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Integer32ToSmi(kScratchRegister, rdx); 662c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ movp(FieldOperand(rbx, RegExpMatchInfo::kNumberOfCapturesOffset), 663f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch kScratchRegister); 664f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Store last subject and last input. 665f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rax, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); 666c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ movp(FieldOperand(rbx, RegExpMatchInfo::kLastSubjectOffset), rax); 667f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rcx, rax); 668c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ RecordWriteField(rbx, RegExpMatchInfo::kLastSubjectOffset, rax, rdi, 669f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch kDontSaveFPRegs); 670f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rax, rcx); 671c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ movp(FieldOperand(rbx, RegExpMatchInfo::kLastInputOffset), rax); 672c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ RecordWriteField(rbx, RegExpMatchInfo::kLastInputOffset, rax, rdi, 673f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch kDontSaveFPRegs); 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 675f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Get the static offsets vector filled by the native regexp code. 676f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadAddress( 677f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch rcx, ExternalReference::address_of_static_offsets_vector(isolate())); 6783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 679c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // rbx: last_match_info (FixedArray) 680f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rcx: offsets vector 681f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdx: number of capture registers 682f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label next_capture, done; 683f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Capture register counter starts from number of capture registers and 684c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // counts down until wrapping after zero. 685f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&next_capture); 686f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ subp(rdx, Immediate(1)); 687f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(negative, &done, Label::kNear); 688f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Read the value from the static offsets vector buffer and make it a smi. 689f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movl(rdi, Operand(rcx, rdx, times_int_size, 0)); 690f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Integer32ToSmi(rdi, rdi); 691f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Store the smi value in the last match info. 692c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ movp(FieldOperand(rbx, rdx, times_pointer_size, 693c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch RegExpMatchInfo::kFirstCaptureOffset), 694f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch rdi); 695f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&next_capture); 696f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&done); 697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 698f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Return last match info. 699c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ movp(rax, rbx); 700f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize); 701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 702f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&exception); 703f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Result must now be exception. If there is no pending exception already a 704f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // stack overflow (on the backtrack stack) was detected in RegExp code but 705f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // haven't created the exception yet. Handle that in the runtime system. 706f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // TODO(592): Rerunning the RegExp to get the stack overflow exception. 707f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference pending_exception_address( 708f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Isolate::kPendingExceptionAddress, isolate()); 709f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Operand pending_exception_operand = 710f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm->ExternalOperand(pending_exception_address, rbx); 711f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rax, pending_exception_operand); 712f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); 713f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(rax, rdx); 714f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &runtime); 7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 716f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // For exception, throw the exception again. 717f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ TailCallRuntime(Runtime::kRegExpExecReThrow); 7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 719f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Do the runtime call to execute the regexp. 720f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&runtime); 721f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ TailCallRuntime(Runtime::kRegExpExec); 72244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 723f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Deferred code for string handling. 724109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (6) Long external string? If not, go to (10). 725f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(¬_seq_nor_cons); 726f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compare flags are still set from (3). 727f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(greater, ¬_long_external, Label::kNear); // Go to (10). 72844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 729109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (7) External string. Short external strings have been ruled out. 730f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&external_string); 731f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 732f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 733f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (FLAG_debug_code) { 734f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Assert that we do not have a cons or slice (indirect strings) here. 735f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Sequential strings have already been ruled out. 736f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(rbx, Immediate(kIsIndirectStringMask)); 737f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Assert(zero, kExternalStringExpectedButNotFound); 738f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 739f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); 740f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Move the pointer so that offset-wise, it looks like a sequential string. 741f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 742f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 743f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kTwoByteStringTag == 0); 744109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (8) Is the external string one byte? If yes, go to (5). 745f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(rbx, Immediate(kStringEncodingMask)); 746109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_zero, &seq_one_byte_string); // Go to (5). 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 748f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdi: subject string (flat two-byte) 749f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rax: RegExp data (FixedArray) 750109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // (9) Two byte sequential. Load regexp code for two byte. Go to (E). 751f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&seq_two_byte_string); 752f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); 753f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Set(rcx, 0); // Type is two byte. 754f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&check_code); // Go to (E). 755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 756f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // (10) Not a string or a short external string? If yes, bail out to runtime. 757f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(¬_long_external); 758f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Catch non-string subject or short external string. 759f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); 760f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); 761f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, &runtime); 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 76362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // (11) Sliced or thin string. Replace subject with parent. Go to (1). 76462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label thin_string; 76562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmpl(rbx, Immediate(kThinStringTag)); 76662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(equal, &thin_string, Label::kNear); 767f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Load offset into r14 and replace subject string with parent. 768f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); 769f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); 770f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&check_underlying); 77162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 77262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ bind(&thin_string); 77362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ movp(rdi, FieldOperand(rdi, ThinString::kActualOffset)); 77462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ jmp(&check_underlying); 775f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#endif // V8_INTERPRETED_REGEXP 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 779f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochstatic int NegativeComparisonResult(Condition cc) { 780f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(cc != equal); 781f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK((cc == less) || (cc == less_equal) 782f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch || (cc == greater) || (cc == greater_equal)); 783f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch return (cc == greater || cc == greater_equal) ? LESS : GREATER; 784f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 787f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochstatic void CheckInputType(MacroAssembler* masm, Register input, 788f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CompareICState::State expected, Label* fail) { 789f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label ok; 790f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (expected == CompareICState::SMI) { 791f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotSmi(input, fail); 792f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else if (expected == CompareICState::NUMBER) { 793f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfSmi(input, &ok); 794f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareMap(input, masm->isolate()->factory()->heap_number_map()); 795f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, fail); 796f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 797f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // We could be strict about internalized/non-internalized here, but as long as 798f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // hydrogen doesn't care, the stub doesn't have to care either. 799f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&ok); 800f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 803f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochstatic void BranchIfNotInternalizedString(MacroAssembler* masm, 804f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label* label, 805f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register object, 806f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register scratch) { 807f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfSmi(object, label); 808f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(scratch, FieldOperand(object, HeapObject::kMapOffset)); 809f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movzxbp(scratch, 810f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(scratch, Map::kInstanceTypeOffset)); 811f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 812f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); 813f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, label); 814f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 817f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CompareICStub::GenerateGeneric(MacroAssembler* masm) { 818f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label runtime_call, check_unequal_objects, done; 819f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Condition cc = GetCondition(); 820f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Factory* factory = isolate()->factory(); 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 822f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label miss; 823f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CheckInputType(masm, rdx, left(), &miss); 824f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CheckInputType(masm, rax, right(), &miss); 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 826f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compare two smis. 827f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label non_smi, smi_done; 828f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotBothSmi(rax, rdx, &non_smi); 829f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ subp(rdx, rax); 830f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(no_overflow, &smi_done); 831f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ notp(rdx); // Correct sign in case of overflow. rdx cannot be 0 here. 832f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&smi_done); 833f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rax, rdx); 834f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 835f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&non_smi); 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 837f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // The compare stub returns a positive, negative, or zero 64-bit integer 838f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // value in rax, corresponding to result of comparing the two inputs. 839f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // NOTICE! This code is only reached after a smi-fast-case check, so 840f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // it is certain that at least one operand isn't a smi. 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 842f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Two identical objects are equal unless they are both NaN or undefined. 843f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch { 844f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label not_identical; 845f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(rax, rdx); 846f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, ¬_identical, Label::kNear); 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 848f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (cc != equal) { 849f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check for undefined. undefined OP undefined is false even though 850f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // undefined == undefined. 851f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); 852109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label check_for_nan; 853109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &check_for_nan, Label::kNear); 854109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Set(rax, NegativeComparisonResult(cc)); 855109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ ret(0); 856109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&check_for_nan); 857f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 858958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 859f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), 860f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // so we do the second best thing - test it ourselves. 861f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label heap_number; 862f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If it's not a heap number, then return equal for (in)equality operator. 863f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 864f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch factory->heap_number_map()); 865f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &heap_number, Label::kNear); 866f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (cc != equal) { 867f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset)); 868f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movzxbl(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset)); 869f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Call runtime on identical objects. Otherwise return equal. 870f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpb(rcx, Immediate(static_cast<uint8_t>(FIRST_JS_RECEIVER_TYPE))); 871f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(above_equal, &runtime_call, Label::kFar); 872f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Call runtime on identical symbols since we need to throw a TypeError. 873f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpb(rcx, Immediate(static_cast<uint8_t>(SYMBOL_TYPE))); 874f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &runtime_call, Label::kFar); 875f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 876f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Set(rax, EQUAL); 877f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 878f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 879f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&heap_number); 880f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // It is a heap number, so return equal if it's not NaN. 881f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // For NaN, return 1 for every condition except greater and 882f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // greater-equal. Return -1 for them, so the comparison yields 883f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // false for all conditions except not-equal. 884f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Set(rax, EQUAL); 885f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); 886f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Ucomisd(xmm0, xmm0); 887f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ setcc(parity_even, rax); 888f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rax is 0 for equal non-NaN heapnumbers, 1 for NaNs. 889f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (cc == greater_equal || cc == greater) { 890f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ negp(rax); 891f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 892f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 893f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 894f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(¬_identical); 895958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 896958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 897f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (cc == equal) { // Both strict and non-strict. 898f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label slow; // Fallthrough label. 899958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 900f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If we're doing a strict equality comparison, we don't have to do 901f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // type conversion, so we generate code to do fast comparison for objects 902f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // and oddballs. Non-smi numbers and strings still go through the usual 903f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // slow-case code. 904f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (strict()) { 905f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If either is a Smi (we know that not both are), then they can only 906f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // be equal if the other is a HeapNumber. If so, use the slow case. 907f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch { 908f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label not_smis; 909f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SelectNonSmi(rbx, rax, rdx, ¬_smis); 910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 911f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check if the non-smi operand is a heap number. 912f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), 913f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch factory->heap_number_map()); 914f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If heap number, handle it in the slow case. 915f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &slow); 916f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Return non-equal. ebx (the lower half of rbx) is not zero. 917f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rax, rbx); 918f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 919958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 920f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(¬_smis); 921f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 923f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If either operand is a JSObject or an oddball value, then they are not 924f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // equal since their pointers are different 925f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // There is no test for undetectability in strict equality. 926958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 927f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If the first object is a JS object, we have done pointer comparison. 928f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 929f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label first_non_object; 930f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rcx); 931f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(below, &first_non_object, Label::kNear); 932f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Return non-zero (rax (not rax) is not zero) 933f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label return_not_equal; 934f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kHeapObjectTag != 0); 935f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&return_not_equal); 936f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 938f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&first_non_object); 939f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check for oddballs: true, false, null, undefined. 940f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CmpInstanceType(rcx, ODDBALL_TYPE); 941f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &return_not_equal); 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 943f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CmpObjectType(rdx, FIRST_JS_RECEIVER_TYPE, rcx); 944f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(above_equal, &return_not_equal); 945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 946f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check for oddballs: true, false, null, undefined. 947f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CmpInstanceType(rcx, ODDBALL_TYPE); 948f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &return_not_equal); 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 950f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Fall through to the general case. 951f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 952f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&slow); 953f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 954958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 955f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Generate the number comparison code. 956f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label non_number_comparison; 957f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label unordered; 958f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison); 959f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ xorl(rax, rax); 960f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ xorl(rcx, rcx); 961f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Ucomisd(xmm0, xmm1); 962f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 963f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Don't base result on EFLAGS when a NaN is involved. 964f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(parity_even, &unordered, Label::kNear); 965f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Return a result of -1, 0, or 1, based on EFLAGS. 966f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ setcc(above, rax); 967f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ setcc(below, rcx); 968f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ subp(rax, rcx); 969f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 970f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 971f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If one of the numbers was NaN, then the result is always false. 972f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // The cc is never not-equal. 973f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&unordered); 974f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(cc != not_equal); 975f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (cc == less || cc == less_equal) { 976f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Set(rax, 1); 977f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 978f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Set(rax, -1); 979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 980f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 982f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // The number comparison code did not provide a valid result. 983f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&non_number_comparison); 984958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 985f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Fast negative check for internalized-to-internalized equality. 986f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label check_for_strings; 987f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (cc == equal) { 988f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch BranchIfNotInternalizedString( 989f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm, &check_for_strings, rax, kScratchRegister); 990f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch BranchIfNotInternalizedString( 991f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm, &check_for_strings, rdx, kScratchRegister); 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 993f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // We've already checked for object identity, so if both operands are 994f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // internalized strings they aren't equal. Register rax (not rax) already 995f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // holds a non-zero value, which indicates not equal, so just return. 996f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 997f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 999f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&check_for_strings); 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1001f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotBothSequentialOneByteStrings(rdx, rax, rcx, rbx, 1002f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch &check_unequal_objects); 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1004f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Inline comparison of one-byte strings. 1005f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (cc == equal) { 1006f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch StringHelper::GenerateFlatOneByteStringEquals(masm, rdx, rax, rcx, rbx); 1007f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 1008f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch StringHelper::GenerateCompareFlatOneByteStrings(masm, rdx, rax, rcx, rbx, 1009f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch rdi, r8); 1010f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1012f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#ifdef DEBUG 1013f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Abort(kUnexpectedFallThroughFromStringComparison); 1014f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#endif 1015f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1016f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&check_unequal_objects); 1017f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (cc == equal && !strict()) { 1018f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Not strict equality. Objects are unequal if 1019f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // they are both JSObjects and not undetectable, 1020f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // and their pointers are different. 10213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label return_equal, return_unequal, undetectable; 1022f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // At most one is a smi, so we can test for smi by adding the two. 1023f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // A smi plus a heap object has the low bit set, a heap object plus 1024f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // a heap object has the low bit clear. 1025f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1026f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kSmiTagMask == 1); 1027f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(rcx, Operand(rax, rdx, times_1, 0)); 1028f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(rcx, Immediate(kSmiTagMask)); 1029f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, &runtime_call, Label::kNear); 1030109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1031109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 1032109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); 1033f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 1034f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Immediate(1 << Map::kIsUndetectable)); 10353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ j(not_zero, &undetectable, Label::kNear); 1036f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(FieldOperand(rcx, Map::kBitFieldOffset), 1037f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Immediate(1 << Map::kIsUndetectable)); 10383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ j(not_zero, &return_unequal, Label::kNear); 1039109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1040109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpInstanceType(rbx, FIRST_JS_RECEIVER_TYPE); 1041109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(below, &runtime_call, Label::kNear); 1042109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpInstanceType(rcx, FIRST_JS_RECEIVER_TYPE); 1043109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(below, &runtime_call, Label::kNear); 1044109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1045f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&return_unequal); 1046109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Return non-equal by returning the non-zero object pointer in rax. 1047109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ ret(0); 1048109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1049109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&undetectable); 1050109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ testb(FieldOperand(rcx, Map::kBitFieldOffset), 1051109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Immediate(1 << Map::kIsUndetectable)); 10523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ j(zero, &return_unequal, Label::kNear); 10533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 10543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // If both sides are JSReceivers, then the result is false according to 10553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // the HTML specification, which says that only comparisons with null or 10563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // undefined are affected by special casing for document.all. 10573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CmpInstanceType(rbx, ODDBALL_TYPE); 10583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ j(zero, &return_equal, Label::kNear); 10593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CmpInstanceType(rcx, ODDBALL_TYPE); 10603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ j(not_zero, &return_unequal, Label::kNear); 10613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 10623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bind(&return_equal); 1063109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Set(rax, EQUAL); 1064f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 1065f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 1066f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&runtime_call); 1067f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1068f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (cc == equal) { 1069109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 1070109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 107162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(rsi); 107262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(strict() ? isolate()->builtins()->StrictEqual() 107362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : isolate()->builtins()->Equal(), 107462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelocInfo::CODE_TARGET); 107562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Pop(rsi); 1076109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1077109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Turn true into 0 and false into some non-zero value. 1078109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(EQUAL == 0); 1079109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(rdx, Heap::kTrueValueRootIndex); 1080109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ subp(rax, rdx); 1081109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 1082f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 1083109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Push arguments below the return address to prepare jump to builtin. 1084109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ PopReturnAddressTo(rcx); 1085109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(rdx); 1086109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(rax); 1087f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(Smi::FromInt(NegativeComparisonResult(cc))); 1088f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ PushReturnAddressFrom(rcx); 1089109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallRuntime(Runtime::kCompare); 1090f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1092f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&miss); 1093f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateMiss(masm); 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1097f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochstatic void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { 1098f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rax : number of arguments to the construct function 1099f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rbx : feedback vector 1100f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdx : slot in feedback vector (Smi) 1101f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdi : the function to call 1102f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1103f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1104f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Number-of-arguments register must be smi-tagged to call out. 1105f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Integer32ToSmi(rax, rax); 1106f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(rax); 1107f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(rdi); 1108f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Integer32ToSmi(rdx, rdx); 1109f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(rdx); 1110f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(rbx); 1111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(rsi); 11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1113f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CallStub(stub); 11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Pop(rsi); 1116f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(rbx); 1117f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(rdx); 1118f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(rdi); 1119f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(rax); 1120f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ SmiToInteger32(rdx, rdx); 1121f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(rax, rax); 11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1125f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochstatic void GenerateRecordCallTarget(MacroAssembler* masm) { 1126f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Cache the called function in a feedback vector slot. Cache states 1127f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // are uninitialized, monomorphic (indicated by a JSFunction), and 1128f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // megamorphic. 1129f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rax : number of arguments to the construct function 1130f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rbx : feedback vector 1131f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdx : slot in feedback vector (Smi) 1132f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdi : the function to call 1133f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Isolate* isolate = masm->isolate(); 113413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label initialize, done, miss, megamorphic, not_array_function; 11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1136f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Load the cache state into r11. 1137f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(rdx, rdx); 1138f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(r11, 1139f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize)); 11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1141f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // A monomorphic cache hit or an already megamorphic state: invoke the 1142f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // function without changing the state. 1143f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // We don't know if r11 is a WeakCell or a Symbol, but it's harmless to read 114462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // at this position in a symbol (see static asserts in feedback-vector.h). 1145f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label check_allocation_site; 1146f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(rdi, FieldOperand(r11, WeakCell::kValueOffset)); 1147f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ j(equal, &done, Label::kFar); 1148f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareRoot(r11, Heap::kmegamorphic_symbolRootIndex); 1149f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &done, Label::kFar); 1150f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareRoot(FieldOperand(r11, HeapObject::kMapOffset), 1151f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Heap::kWeakCellMapRootIndex); 1152f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &check_allocation_site); 1153592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1154f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If the weak cell is cleared, we have a new chance to become monomorphic. 1155f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CheckSmi(FieldOperand(r11, WeakCell::kValueOffset)); 1156f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &initialize); 1157f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&megamorphic); 1158592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1159f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&check_allocation_site); 1160f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If we came here, we need to see if we are the array function. 1161f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If we didn't have a matching function, and we didn't find the megamorph 1162f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // sentinel, then we have in the slot either some other function or an 1163f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // AllocationSite. 1164f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareRoot(FieldOperand(r11, 0), Heap::kAllocationSiteMapRootIndex); 1165f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &miss); 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1167f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Make sure the function is the Array() function 1168f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r11); 1169f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(rdi, r11); 1170f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &megamorphic); 1171f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ jmp(&done); 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1173f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&miss); 11748389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 1175f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // A monomorphic miss (i.e, here the cache is not uninitialized) goes 1176f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // megamorphic. 1177f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareRoot(r11, Heap::kuninitialized_symbolRootIndex); 1178f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &initialize); 1179f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // MegamorphicSentinel is an immortal immovable object (undefined) so no 1180f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // write-barrier is needed. 1181f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&megamorphic); 1182f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), 118362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackVector::MegamorphicSentinel(isolate)); 1184f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&done); 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1186f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // An uninitialized cache is patched with the function or sentinel to 1187f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // indicate the ElementsKind if function is the Array constructor. 1188f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&initialize); 118980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1190f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Make sure the function is the Array() function 1191f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r11); 1192f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(rdi, r11); 1193f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, ¬_array_function); 119480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1195f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CreateAllocationSiteStub create_stub(isolate); 1196f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CallStubInRecordCallTarget(masm, &create_stub); 1197f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ jmp(&done); 119880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1199f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(¬_array_function); 1200f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CreateWeakCellStub weak_cell_stub(isolate); 1201f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CallStubInRecordCallTarget(masm, &weak_cell_stub); 120213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1203f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&done); 1204f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Increment the call count for all function calls. 120513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size, 120613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FixedArray::kHeaderSize + kPointerSize), 120713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Smi::FromInt(1)); 1208f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 120980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 121080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1211f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CallConstructStub::Generate(MacroAssembler* masm) { 1212f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rax : number of arguments 1213f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rbx : feedback vector 1214f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdx : slot in feedback vector (Smi) 1215f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rdi : constructor function 121680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1217f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label non_function; 1218f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that the constructor is not a smi. 1219f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfSmi(rdi, &non_function); 1220f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that constructor is a JSFunction. 1221f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CmpObjectType(rdi, JS_FUNCTION_TYPE, r11); 1222f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &non_function); 1223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1224f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateRecordCallTarget(masm); 122580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1226f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label feedback_register_initialized; 1227f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Put the AllocationSite from the feedback vector into rbx, or undefined. 1228f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rbx, 1229f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize)); 1230f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareRoot(FieldOperand(rbx, 0), Heap::kAllocationSiteMapRootIndex); 1231f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &feedback_register_initialized, Label::kNear); 1232f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); 1233f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&feedback_register_initialized); 1234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1235f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ AssertUndefinedOrAllocationSite(rbx); 1236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1237f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Pass new target to construct stub. 1238f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rdx, rdi); 123980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1240f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Tail call to the function-specific construct stub (still in the caller 1241f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // context at this point). 1242f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); 1243f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset)); 1244f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); 1245f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(rcx); 124680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1247f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&non_function); 1248f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rdx, rdi); 1249f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 1250f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1252f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochbool CEntryStub::NeedsImmovableCode() { 1253f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch return false; 1254f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 125580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 125680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1257f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 1258f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CEntryStub::GenerateAheadOfTime(isolate); 1259f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 1260f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 1261f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // It is important that the store buffer overflow stubs are generated first. 126213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate); 1263f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 1264f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CreateWeakCellStub::GenerateAheadOfTime(isolate); 1265f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch BinaryOpICStub::GenerateAheadOfTime(isolate); 1266f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 1267f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch StoreFastElementStub::GenerateAheadOfTime(isolate); 126880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 126980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 127080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1271f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CodeStub::GenerateFPStubs(Isolate* isolate) { 1272f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 127380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 127480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1275f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 1276f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CEntryStub stub(isolate, 1, kDontSaveFPRegs); 1277f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch stub.GetCode(); 1278f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CEntryStub save_doubles(isolate, 1, kSaveFPRegs); 1279f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch save_doubles.GetCode(); 128080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 128180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 128280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1283f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CEntryStub::Generate(MacroAssembler* masm) { 1284f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rax: number of arguments including receiver 1285f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rbx: pointer to C function (C callee-saved) 1286f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rbp: frame pointer of calling JS frame (restored after C call) 1287f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rsp: stack pointer (restored after C call) 1288f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rsi: current context (restored) 1289f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // 1290f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If argv_in_register(): 1291f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r15: pointer to the first argument 129280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1293f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm); 1294f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1295f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#ifdef _WIN64 1296109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9. It requires the 1297109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // stack to be aligned to 16 bytes. It only allows a single-word to be 1298109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // returned in register rax. Larger return sizes must be written to an address 1299109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // passed as a hidden first argument. 1300109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const Register kCCallArg0 = rcx; 1301109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const Register kCCallArg1 = rdx; 1302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const Register kCCallArg2 = r8; 1303109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const Register kCCallArg3 = r9; 1304109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kArgExtraStackSpace = 2; 1305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kMaxRegisterResultSize = 1; 1306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else 1307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // GCC / Clang passes arguments in rdi, rsi, rdx, rcx, r8, r9. Simple results 1308109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // are returned in rax, and a struct of two pointers are returned in rax+rdx. 1309109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Larger return sizes must be written to an address passed as a hidden first 1310109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // argument. 1311109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const Register kCCallArg0 = rdi; 1312109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const Register kCCallArg1 = rsi; 1313109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const Register kCCallArg2 = rdx; 1314109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const Register kCCallArg3 = rcx; 1315109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kArgExtraStackSpace = 0; 1316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kMaxRegisterResultSize = 2; 1317f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#endif // _WIN64 1318109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1319109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Enter the exit frame that transitions from JavaScript to C++. 1320109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int arg_stack_space = 1321109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kArgExtraStackSpace + 1322109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch (result_size() <= kMaxRegisterResultSize ? 0 : result_size()); 1323f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (argv_in_register()) { 1324f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(!save_doubles()); 1325f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(!is_builtin_exit()); 1326f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ EnterApiExitFrame(arg_stack_space); 1327f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Move argc into r14 (argv is already in r15). 1328f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(r14, rax); 1329f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 1330f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterExitFrame( 1331f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch arg_stack_space, save_doubles(), 1332f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch is_builtin_exit() ? StackFrame::BUILTIN_EXIT : StackFrame::EXIT); 133380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 133480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1335f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rbx: pointer to builtin function (C callee-saved). 1336f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rbp: frame pointer of exit frame (restored after C call). 1337f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rsp: stack pointer (restored after C call). 1338f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r14: number of arguments including receiver (C callee-saved). 1339f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r15: argv pointer (C callee-saved). 134080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1341f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check stack alignment. 1342f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (FLAG_debug_code) { 1343f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CheckStackAlignment(); 1344f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 134580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1346109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Call C function. The arguments object will be created by stubs declared by 1347109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // DECLARE_RUNTIME_FUNCTION(). 1348109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (result_size() <= kMaxRegisterResultSize) { 1349f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Pass a pointer to the Arguments object as the first argument. 1350109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Return result in single register (rax), or a register pair (rax, rdx). 1351109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(kCCallArg0, r14); // argc. 1352109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(kCCallArg1, r15); // argv. 1353109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Move(kCCallArg2, ExternalReference::isolate_address(isolate())); 1354f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 1355109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK_LE(result_size(), 3); 1356f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Pass a pointer to the result location as the first argument. 1357109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ leap(kCCallArg0, StackSpaceOperand(kArgExtraStackSpace)); 1358f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Pass a pointer to the Arguments object as the second argument. 1359109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(kCCallArg1, r14); // argc. 1360109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(kCCallArg2, r15); // argv. 1361109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Move(kCCallArg3, ExternalReference::isolate_address(isolate())); 136280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1363f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ call(rbx); 136480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1365109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (result_size() > kMaxRegisterResultSize) { 1366f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Read result values stored on stack. Result is stored 1367109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // above the the two Arguments object slots on Win64. 1368109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK_LE(result_size(), 3); 1369109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movq(kReturnRegister0, StackSpaceOperand(kArgExtraStackSpace + 0)); 1370109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movq(kReturnRegister1, StackSpaceOperand(kArgExtraStackSpace + 1)); 1371109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (result_size() > 2) { 1372109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movq(kReturnRegister2, StackSpaceOperand(kArgExtraStackSpace + 2)); 1373109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1374f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 1375109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Result is in rax, rdx:rax or r8:rdx:rax - do not destroy these registers! 137680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1377f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check result for exception sentinel. 1378f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label exception_returned; 1379f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareRoot(rax, Heap::kExceptionRootIndex); 1380f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &exception_returned); 138180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1382f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that there is no pending exception, otherwise we 1383f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // should have returned the exception sentinel. 1384f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (FLAG_debug_code) { 1385f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label okay; 1386f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadRoot(r14, Heap::kTheHoleValueRootIndex); 1387f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference pending_exception_address( 1388f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Isolate::kPendingExceptionAddress, isolate()); 1389f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Operand pending_exception_operand = 1390f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm->ExternalOperand(pending_exception_address); 1391f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(r14, pending_exception_operand); 1392f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &okay, Label::kNear); 1393f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ int3(); 1394f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&okay); 1395f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 139680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1397f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Exit the JavaScript to C++ exit frame. 1398f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LeaveExitFrame(save_doubles(), !argv_in_register()); 1399f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 140080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1401f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Handling of exception. 1402f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&exception_returned); 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1404f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference pending_handler_context_address( 1405f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Isolate::kPendingHandlerContextAddress, isolate()); 1406f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference pending_handler_code_address( 1407f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Isolate::kPendingHandlerCodeAddress, isolate()); 1408f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference pending_handler_offset_address( 1409f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Isolate::kPendingHandlerOffsetAddress, isolate()); 1410f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference pending_handler_fp_address( 1411f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Isolate::kPendingHandlerFPAddress, isolate()); 1412f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference pending_handler_sp_address( 1413f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Isolate::kPendingHandlerSPAddress, isolate()); 141480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1415f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Ask the runtime for help to determine the handler. This will set rax to 1416f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // contain the current pending exception, don't clobber it. 1417f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler, 1418f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch isolate()); 1419f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch { 1420f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1421f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(arg_reg_1, Immediate(0)); // argc. 1422f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(arg_reg_2, Immediate(0)); // argv. 1423f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(arg_reg_3, ExternalReference::isolate_address(isolate())); 1424f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ PrepareCallCFunction(3); 1425f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CallCFunction(find_handler, 3); 1426f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 142780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1428f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Retrieve the handler context, SP and FP. 1429f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rsi, masm->ExternalOperand(pending_handler_context_address)); 1430f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rsp, masm->ExternalOperand(pending_handler_sp_address)); 1431f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rbp, masm->ExternalOperand(pending_handler_fp_address)); 143280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1433f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If the handler is a JS frame, restore the context to the frame. Note that 1434f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // the context will be set to (rsi == 0) for non-JS frames. 1435f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label skip; 1436f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testp(rsi, rsi); 1437f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(zero, &skip, Label::kNear); 1438f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 1439f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&skip); 144080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1441f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compute the handler entry address and jump to it. 1442f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rdi, masm->ExternalOperand(pending_handler_code_address)); 1443f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rdx, masm->ExternalOperand(pending_handler_offset_address)); 1444f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(rdi, FieldOperand(rdi, rdx, times_1, Code::kHeaderSize)); 1445f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(rdi); 1446f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 144780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1449f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid JSEntryStub::Generate(MacroAssembler* masm) { 1450f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label invoke, handler_entry, exit; 1451f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label not_outermost_js, not_outermost_js_2; 14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1453f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm); 14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1455f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch { // NOLINT. Scope block confuses linter. 1456f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch MacroAssembler::NoRootArrayScope uninitialized_root_register(masm); 1457f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Set up frame. 1458f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ pushq(rbp); 1459f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rbp, rsp); 14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Push the stack frame type. 146262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(Immediate(StackFrame::TypeToMarker(type()))); // context slot 14633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ExternalReference context_address(Isolate::kContextAddress, isolate()); 14643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Load(kScratchRegister, context_address); 14653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Push(kScratchRegister); // context 1466f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Save callee-saved registers (X64/X32/Win64 calling conventions). 1467f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ pushq(r12); 1468f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ pushq(r13); 1469f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ pushq(r14); 1470f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ pushq(r15); 1471f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#ifdef _WIN64 1472f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ pushq(rdi); // Only callee save in Win64 ABI, argument in AMD64 ABI. 1473f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ pushq(rsi); // Only callee save in Win64 ABI, argument in AMD64 ABI. 1474f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#endif 1475f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ pushq(rbx); 14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1477f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#ifdef _WIN64 1478f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // On Win64 XMM6-XMM15 are callee-save 1479f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ subp(rsp, Immediate(EntryFrameConstants::kXMMRegistersBlockSize)); 1480f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0), xmm6); 1481f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1), xmm7); 1482f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 2), xmm8); 1483f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 3), xmm9); 1484f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 4), xmm10); 1485f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 5), xmm11); 1486f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 6), xmm12); 1487f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 7), xmm13); 1488f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 8), xmm14); 1489f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 9), xmm15); 1490f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#endif 149180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1492f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Set up the roots and smi constant registers. 1493f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Needs to be done before any further smi loads. 1494f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ InitializeRootRegister(); 1495f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 1496589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1497f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Save copies of the top frame descriptor on the stack. 1498f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference c_entry_fp(Isolate::kCEntryFPAddress, isolate()); 1499f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch { 1500f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp); 1501f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(c_entry_fp_operand); 1502589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 150380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1504f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If this is the outermost JS call, set js_entry_sp value. 1505f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate()); 1506f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Load(rax, js_entry_sp); 1507f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testp(rax, rax); 1508f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, ¬_outermost_js); 150962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(Immediate(StackFrame::OUTERMOST_JSENTRY_FRAME)); 1510f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rax, rbp); 1511f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Store(js_entry_sp, rax); 1512f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label cont; 1513f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&cont); 1514f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(¬_outermost_js); 151562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(Immediate(StackFrame::INNER_JSENTRY_FRAME)); 1516f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&cont); 15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1518f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Jump to a faked try block that does the invoke, with a faked catch 1519f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // block that sets the pending exception. 1520f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&invoke); 1521f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&handler_entry); 1522f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch handler_offset_ = handler_entry.pos(); 1523f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Caught exception: Store result (exception) in the pending exception 1524f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // field in the JSEnv and return a failure sentinel. 1525f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference pending_exception(Isolate::kPendingExceptionAddress, 1526f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch isolate()); 1527f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Store(pending_exception, rax); 1528f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadRoot(rax, Heap::kExceptionRootIndex); 1529f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&exit); 15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1531f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Invoke: Link this frame into the handler chain. 1532f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&invoke); 1533f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ PushStackHandler(); 153480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1535f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Fake a receiver (NULL). 1536f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(Immediate(0)); // receiver 1537f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1538f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Invoke the function by calling through JS entry trampoline builtin and 1539f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // pop the faked function when we return. We load the address from an 1540f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // external reference instead of inlining the call target address directly 1541f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // in the code, because the builtin stubs may not have been generated yet 1542f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // at the time this code is generated. 1543f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (type() == StackFrame::ENTRY_CONSTRUCT) { 1544f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline, 1545f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch isolate()); 1546f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Load(rax, construct_entry); 1547f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 1548f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference entry(Builtins::kJSEntryTrampoline, isolate()); 1549f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Load(rax, entry); 155085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 1551f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(kScratchRegister, FieldOperand(rax, Code::kHeaderSize)); 1552f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ call(kScratchRegister); 155380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1554f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Unlink this frame from the handler chain. 1555f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ PopStackHandler(); 155680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1557f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&exit); 1558f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check if the current stack frame is marked as the outermost JS frame. 1559f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(rbx); 156062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmpp(rbx, Immediate(StackFrame::OUTERMOST_JSENTRY_FRAME)); 1561f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, ¬_outermost_js_2); 1562f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(kScratchRegister, js_entry_sp); 1563f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(Operand(kScratchRegister, 0), Immediate(0)); 1564f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(¬_outermost_js_2); 156580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1566f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Restore the top frame descriptor from the stack. 1567f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch { Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp); 1568f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(c_entry_fp_operand); 156985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 157080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1571f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Restore callee-saved registers (X64 conventions). 1572f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#ifdef _WIN64 1573f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // On Win64 XMM6-XMM15 are callee-save 1574f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(xmm6, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0)); 1575f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(xmm7, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1)); 1576f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(xmm8, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 2)); 1577f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(xmm9, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 3)); 1578f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(xmm10, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 4)); 1579f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(xmm11, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 5)); 1580f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(xmm12, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 6)); 1581f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(xmm13, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 7)); 1582f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(xmm14, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 8)); 1583f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movdqu(xmm15, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 9)); 1584f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ addp(rsp, Immediate(EntryFrameConstants::kXMMRegistersBlockSize)); 1585f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#endif 158680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1587f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ popq(rbx); 1588f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#ifdef _WIN64 1589f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI. 1590f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ popq(rsi); 1591f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ popq(rdi); 1592f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#endif 1593f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ popq(r15); 1594f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ popq(r14); 1595f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ popq(r13); 1596f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ popq(r12); 1597f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ addp(rsp, Immediate(2 * kPointerSize)); // remove markers 1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1599f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Restore frame pointer and return. 1600f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ popq(rbp); 1601f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 160280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 160380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 160480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1605f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch// ------------------------------------------------------------------------- 1606f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch// StringCharCodeAtGenerator 16078389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 1608f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 1609f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If the receiver is a smi trigger the non-string case. 1610f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (check_mode_ == RECEIVER_IS_UNKNOWN) { 1611f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfSmi(object_, receiver_not_string_); 16128389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 1613f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Fetch the instance type of the receiver into result register. 1614f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(result_, FieldOperand(object_, HeapObject::kMapOffset)); 1615f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 1616f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If the receiver is not a string trigger the non-string case. 1617f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(result_, Immediate(kIsNotStringMask)); 1618f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, receiver_not_string_); 1619f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 16208389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 1621f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If the index is non-smi trigger the non-smi case. 1622f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotSmi(index_, &index_not_smi_); 1623f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&got_smi_index_); 16248389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 1625f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check for index out of range. 1626f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiCompare(index_, FieldOperand(object_, String::kLengthOffset)); 1627f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(above_equal, index_out_of_range_); 16288389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 1629f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(index_, index_); 16308389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 1631f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch StringCharLoadGenerator::Generate( 1632f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm, object_, index_, result_, &call_runtime_); 1633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1634f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Integer32ToSmi(result_, result_); 1635f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&exit_); 1636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1639f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid StringCharCodeAtGenerator::GenerateSlow( 1640f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch MacroAssembler* masm, EmbedMode embed_mode, 1641f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch const RuntimeCallHelper& call_helper) { 1642f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase); 1643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1644f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Factory* factory = masm->isolate()->factory(); 1645f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Index is not a smi. 1646f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&index_not_smi_); 1647f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If index is a heap number, try converting it to an integer. 1648f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CheckMap(index_, 1649f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch factory->heap_number_map(), 1650f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch index_not_number_, 1651f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DONT_DO_SMI_CHECK); 1652f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch call_helper.BeforeCall(masm); 1653f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (embed_mode == PART_OF_IC_HANDLER) { 1654f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(LoadWithVectorDescriptor::VectorRegister()); 1655f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(LoadDescriptor::SlotRegister()); 1656f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 1657f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(object_); 1658f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(index_); // Consumed by runtime conversion function. 165913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ CallRuntime(Runtime::kNumberToSmi); 1660f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (!index_.is(rax)) { 1661f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Save the conversion result before the pop instructions below 1662f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // have a chance to overwrite it. 1663f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(index_, rax); 1664f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 1665f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(object_); 1666f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (embed_mode == PART_OF_IC_HANDLER) { 1667f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(LoadDescriptor::SlotRegister()); 1668f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(LoadWithVectorDescriptor::VectorRegister()); 1669f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 1670f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Reload the instance type. 1671f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(result_, FieldOperand(object_, HeapObject::kMapOffset)); 1672f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 1673f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch call_helper.AfterCall(masm); 1674f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If index is still not a smi, it must be out of range. 1675f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotSmi(index_, index_out_of_range_); 1676f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Otherwise, return to the fast path. 1677f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&got_smi_index_); 1678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1679f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Call runtime. We get here when the receiver is a string and the 1680f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // index is a number, but the code of getting the actual character 1681f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // is too complex (e.g., when the string needs to be flattened). 1682f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&call_runtime_); 1683f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch call_helper.BeforeCall(masm); 1684f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(object_); 1685f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Integer32ToSmi(index_, index_); 1686f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(index_); 1687f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CallRuntime(Runtime::kStringCharCodeAtRT); 1688f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (!result_.is(rax)) { 1689f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(result_, rax); 1690f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 1691f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch call_helper.AfterCall(masm); 1692f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&exit_); 1693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1694f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); 1695f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 1696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1697f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, 1698f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register left, 1699f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register right, 1700f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register scratch1, 1701f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register scratch2) { 1702f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register length = scratch1; 1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1704f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compare lengths. 1705f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label check_zero_length; 1706f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(length, FieldOperand(left, String::kLengthOffset)); 1707f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiCompare(length, FieldOperand(right, String::kLengthOffset)); 1708f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &check_zero_length, Label::kNear); 1709f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(rax, Smi::FromInt(NOT_EQUAL)); 1710f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1712f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check if the length is zero. 1713f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label compare_chars; 1714f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&check_zero_length); 1715f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1716f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiTest(length); 1717f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, &compare_chars, Label::kNear); 1718f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(rax, Smi::FromInt(EQUAL)); 1719f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1721f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compare characters. 1722f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&compare_chars); 1723f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label strings_not_equal; 1724f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, 1725f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch &strings_not_equal, Label::kNear); 1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1727f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Characters are equal. 1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rax, Smi::FromInt(EQUAL)); 1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1731f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Characters are not equal. 1732f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&strings_not_equal); 1733f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(rax, Smi::FromInt(NOT_EQUAL)); 1734f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1738f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid StringHelper::GenerateCompareFlatOneByteStrings( 1739f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch MacroAssembler* masm, Register left, Register right, Register scratch1, 1740f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register scratch2, Register scratch3, Register scratch4) { 1741f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Ensure that you can always subtract a string length from a non-negative 1742f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // number (e.g. another length). 1743f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(String::kMaxLength < 0x7fffffff); 1744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1745f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Find minimum length and length difference. 1746f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(scratch1, FieldOperand(left, String::kLengthOffset)); 1747f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(scratch4, scratch1); 1748f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiSub(scratch4, 1749f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch scratch4, 1750f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(right, String::kLengthOffset)); 1751f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Register scratch4 now holds left.length - right.length. 1752f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch const Register length_difference = scratch4; 1753f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label left_shorter; 1754f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(less, &left_shorter, Label::kNear); 1755f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // The right string isn't longer that the left one. 1756f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Get the right string's length by subtracting the (non-negative) difference 1757f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // from the left string's length. 1758f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiSub(scratch1, scratch1, length_difference); 1759f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&left_shorter); 1760f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Register scratch1 now holds Min(left.length, right.length). 1761f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch const Register min_length = scratch1; 1762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1763f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label compare_lengths; 1764f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If min-length is zero, go directly to comparing lengths. 1765f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiTest(min_length); 1766f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(zero, &compare_lengths, Label::kNear); 1767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1768f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compare loop. 1769f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label result_not_equal; 1770f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateOneByteCharsCompareLoop( 1771f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm, left, right, min_length, scratch2, &result_not_equal, 1772f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // In debug-code mode, SmiTest below might push 1773f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // the target label outside the near range. 1774f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label::kFar); 1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1776f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Completed loop without finding different characters. 1777f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compare lengths (precomputed). 1778f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&compare_lengths); 1779f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiTest(length_difference); 1780f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label length_not_equal; 1781f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, &length_not_equal, Label::kNear); 1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1783f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Result is EQUAL. 1784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(rax, Smi::FromInt(EQUAL)); 1785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1787f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label result_greater; 1788f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label result_less; 1789f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&length_not_equal); 1790f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(greater, &result_greater, Label::kNear); 1791f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&result_less, Label::kNear); 1792f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&result_not_equal); 1793f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Unequal comparison of left to right, either character or length. 1794f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(above, &result_greater, Label::kNear); 1795f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&result_less); 1796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1797f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Result is LESS. 1798f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(rax, Smi::FromInt(LESS)); 1799f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 1800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1801f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Result is GREATER. 1802f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&result_greater); 1803f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(rax, Smi::FromInt(GREATER)); 1804f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 1805f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 1806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 18073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1808f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid StringHelper::GenerateOneByteCharsCompareLoop( 1809f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch MacroAssembler* masm, Register left, Register right, Register length, 1810f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register scratch, Label* chars_not_equal, Label::Distance near_jump) { 1811f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Change index to run from -length to -1 by adding length to string 1812f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // start. This means that loop ends when index reaches zero, which 1813f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // doesn't need an additional compare. 1814f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(length, length); 1815f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(left, 1816f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize)); 1817f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(right, 1818f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(right, length, times_1, SeqOneByteString::kHeaderSize)); 1819f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ negq(length); 1820f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register index = length; // index = -length; 1821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1822f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compare loop. 1823f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label loop; 1824f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&loop); 1825f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movb(scratch, Operand(left, index, times_1, 0)); 1826f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpb(scratch, Operand(right, index, times_1, 0)); 1827f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, chars_not_equal, near_jump); 1828f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ incq(index); 1829f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, &loop); 1830f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 1831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1833f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { 1834f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // ----------- S t a t e ------------- 1835f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // -- rdx : left 1836f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // -- rax : right 1837f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // -- rsp[0] : return address 1838f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // ----------------------------------- 18391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1840f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Load rcx with the allocation site. We stick an undefined dummy value here 1841f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // and replace it with the real allocation site later when we instantiate this 1842f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate(). 184313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Move(rcx, isolate()->factory()->undefined_value()); 18441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1845f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Make sure that we actually patched the allocation site. 1846f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (FLAG_debug_code) { 1847f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(rcx, Immediate(kSmiTagMask)); 1848f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Assert(not_equal, kExpectedAllocationSite); 1849f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), 1850f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch isolate()->factory()->allocation_site_map()); 1851f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Assert(equal, kExpectedAllocationSite); 1852f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 18531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1854f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Tail call into the stub that handles binary operations with allocation 1855f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // sites. 1856f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch BinaryOpWithAllocationSiteStub stub(isolate(), state()); 1857f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ TailCallStub(&stub); 1858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1861f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CompareICStub::GenerateBooleans(MacroAssembler* masm) { 1862f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK_EQ(CompareICState::BOOLEAN, state()); 18633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss; 1864f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label::Distance const miss_distance = 1865f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm->emit_debug_code() ? Label::kFar : Label::kNear; 18661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1867f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfSmi(rdx, &miss, miss_distance); 1868f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); 1869f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfSmi(rax, &miss, miss_distance); 1870f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 1871f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotRoot(rcx, Heap::kBooleanMapRootIndex, &miss, miss_distance); 1872f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotRoot(rbx, Heap::kBooleanMapRootIndex, &miss, miss_distance); 1873109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!Token::IsEqualityOp(op())) { 1874109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rax, FieldOperand(rax, Oddball::kToNumberOffset)); 1875109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertSmi(rax); 1876109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rdx, FieldOperand(rdx, Oddball::kToNumberOffset)); 1877109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertSmi(rdx); 1878109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ pushq(rax); 1879109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movq(rax, rdx); 1880109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ popq(rdx); 1881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1882109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ subp(rax, rdx); 1883109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 188485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 18853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&miss); 18863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMiss(masm); 18873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1890f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CompareICStub::GenerateSmis(MacroAssembler* masm) { 1891f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(state() == CompareICState::SMI); 1892f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label miss; 1893f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); 18943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1895f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (GetCondition() == equal) { 1896f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // For equality we do not care about the sign of the result. 1897f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ subp(rax, rdx); 1898f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 1899f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label done; 1900f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ subp(rdx, rax); 1901f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(no_overflow, &done, Label::kNear); 1902f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Correct sign of result in case of overflow. 1903f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ notp(rdx); 1904f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&done); 1905f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rax, rdx); 19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1907f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 19081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1909f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&miss); 1910f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateMiss(masm); 19111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 19121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 19131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1914f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CompareICStub::GenerateNumbers(MacroAssembler* masm) { 1915f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(state() == CompareICState::NUMBER); 1916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1917f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label generic_stub; 1918f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label unordered, maybe_undefined1, maybe_undefined2; 1919f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label miss; 19203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1921f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (left() == CompareICState::SMI) { 1922f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotSmi(rdx, &miss); 1923f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 1924f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (right() == CompareICState::SMI) { 1925f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotSmi(rax, &miss); 1926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1928f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Load left and right operand. 1929f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label done, left, left_smi, right_smi; 1930f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfSmi(rax, &right_smi, Label::kNear); 1931f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareMap(rax, isolate()->factory()->heap_number_map()); 1932f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &maybe_undefined1, Label::kNear); 1933f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); 1934f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&left, Label::kNear); 1935f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&right_smi); 1936f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(rcx, rax); // Can't clobber rax yet. 1937f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Cvtlsi2sd(xmm1, rcx); 1938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1939f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&left); 1940f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfSmi(rdx, &left_smi, Label::kNear); 1941f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareMap(rdx, isolate()->factory()->heap_number_map()); 1942f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &maybe_undefined2, Label::kNear); 1943f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); 1944f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&done); 1945f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&left_smi); 1946f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(rcx, rdx); // Can't clobber rdx yet. 1947f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Cvtlsi2sd(xmm0, rcx); 1948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1949f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&done); 1950f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compare operands 1951f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Ucomisd(xmm0, xmm1); 1952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1953f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Don't base result on EFLAGS when a NaN is involved. 1954f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(parity_even, &unordered, Label::kNear); 1955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1956f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Return a result of -1, 0, or 1, based on EFLAGS. 1957f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Performing mov, because xor would destroy the flag register. 1958f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movl(rax, Immediate(0)); 1959f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movl(rcx, Immediate(0)); 1960f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ setcc(above, rax); // Add one to zero if carry clear and not equal. 1961f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ sbbp(rax, rcx); // Subtract one if below (aka. carry set). 1962f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 1963f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1964f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&unordered); 1965f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&generic_stub); 1966109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CompareICStub stub(isolate(), op(), CompareICState::GENERIC, 1967f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CompareICState::GENERIC, CompareICState::GENERIC); 1968f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); 1969f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 1970f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&maybe_undefined1); 1971f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (Token::IsOrderedRelationalCompareOp(op())) { 1972f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Cmp(rax, isolate()->factory()->undefined_value()); 1973f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &miss); 1974f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfSmi(rdx, &unordered); 1975f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); 1976f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &maybe_undefined2, Label::kNear); 1977f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&unordered); 1978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1980f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&maybe_undefined2); 1981f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (Token::IsOrderedRelationalCompareOp(op())) { 1982f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Cmp(rdx, isolate()->factory()->undefined_value()); 1983f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &unordered); 1984f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 1985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1986f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&miss); 1987f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateMiss(masm); 1988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1991f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { 1992f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(state() == CompareICState::INTERNALIZED_STRING); 1993f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(GetCondition() == equal); 1994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1995f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Registers containing left and right operands respectively. 1996f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register left = rdx; 1997f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register right = rax; 1998f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register tmp1 = rcx; 1999f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register tmp2 = rbx; 2000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2001f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that both operands are heap objects. 2002f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label miss; 2003f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Condition cond = masm->CheckEitherSmi(left, right, tmp1); 2004f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(cond, &miss, Label::kNear); 2005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2006f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that both operands are internalized strings. 2007f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 2008f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 2009f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 2010f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 2011f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 2012f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ orp(tmp1, tmp2); 2013f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); 2014f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, &miss, Label::kNear); 2015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2016f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Internalized strings are compared by identity. 2017f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label done; 2018f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(left, right); 2019f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Make sure rax is non-zero. At this point input operands are 2020f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // guaranteed to be non-zero. 2021f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(right.is(rax)); 2022f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &done, Label::kNear); 2023f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(EQUAL == 0); 2024f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 2025f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(rax, Smi::FromInt(EQUAL)); 2026f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&done); 2027f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 2028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2029f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&miss); 2030f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateMiss(masm); 2031f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 2032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2034f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { 2035f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(state() == CompareICState::UNIQUE_NAME); 2036f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(GetCondition() == equal); 2037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2038f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Registers containing left and right operands respectively. 2039f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register left = rdx; 2040f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register right = rax; 2041f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register tmp1 = rcx; 2042f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register tmp2 = rbx; 2043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2044f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that both operands are heap objects. 2045f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label miss; 2046f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Condition cond = masm->CheckEitherSmi(left, right, tmp1); 2047f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(cond, &miss, Label::kNear); 2048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2049f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that both operands are unique names. This leaves the instance 2050f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // types loaded in tmp1 and tmp2. 2051f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 2052f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 2053f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 2054f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 2055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2056f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotUniqueNameInstanceType(tmp1, &miss, Label::kNear); 2057f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotUniqueNameInstanceType(tmp2, &miss, Label::kNear); 2058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2059f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Unique names are compared by identity. 2060f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label done; 2061f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(left, right); 2062f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Make sure rax is non-zero. At this point input operands are 2063f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // guaranteed to be non-zero. 2064f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(right.is(rax)); 2065f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &done, Label::kNear); 2066f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(EQUAL == 0); 2067f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 2068f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(rax, Smi::FromInt(EQUAL)); 2069f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&done); 2070f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 2071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2072f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&miss); 2073f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateMiss(masm); 2074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2077f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CompareICStub::GenerateStrings(MacroAssembler* masm) { 2078f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(state() == CompareICState::STRING); 2079f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label miss; 20803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2081f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch bool equality = Token::IsEqualityOp(op()); 20823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2083f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Registers containing left and right operands respectively. 2084f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register left = rdx; 2085f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register right = rax; 2086f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register tmp1 = rcx; 2087f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register tmp2 = rbx; 2088f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register tmp3 = rdi; 20893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2090f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that both operands are heap objects. 2091f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Condition cond = masm->CheckEitherSmi(left, right, tmp1); 2092f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(cond, &miss); 20933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2094f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that both operands are strings. This leaves the instance 2095f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // types loaded in tmp1 and tmp2. 2096f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 2097f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 2098f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 2099f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 2100f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(tmp3, tmp1); 2101f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kNotStringTag != 0); 2102f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ orp(tmp3, tmp2); 2103f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(tmp3, Immediate(kIsNotStringMask)); 2104f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, &miss); 2105f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2106f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Fast check for identical strings. 2107f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label not_same; 2108f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(left, right); 2109f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, ¬_same, Label::kNear); 2110f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(EQUAL == 0); 2111f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 2112f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(rax, Smi::FromInt(EQUAL)); 2113f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 2114f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2115f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Handle not identical strings. 2116f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(¬_same); 2117f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2118f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that both strings are internalized strings. If they are, we're done 2119f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // because we already know they are not identical. We also know they are both 2120f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // strings. 2121f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (equality) { 2122f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label do_compare; 2123f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kInternalizedTag == 0); 2124f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ orp(tmp1, tmp2); 2125f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testb(tmp1, Immediate(kIsNotInternalizedMask)); 2126f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, &do_compare, Label::kNear); 2127f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Make sure rax is non-zero. At this point input operands are 2128f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // guaranteed to be non-zero. 2129f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(right.is(rax)); 21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 2131f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&do_compare); 21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 21333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2134f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check that both strings are sequential one-byte. 2135f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label runtime; 2136f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotBothSequentialOneByteStrings(left, right, tmp1, tmp2, &runtime); 21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2138f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compare flat one-byte strings. Returns when done. 2139f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (equality) { 2140f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, 2141f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch tmp2); 2142f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 2143f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch StringHelper::GenerateCompareFlatOneByteStrings( 2144f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm, left, right, tmp1, tmp2, tmp3, kScratchRegister); 2145f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 21463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2147f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Handle more complex cases in runtime. 2148f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&runtime); 2149f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (equality) { 21503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 21513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 21523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Push(left); 21533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Push(right); 21543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CallRuntime(Runtime::kStringEqual); 21553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 21563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadRoot(rdx, Heap::kTrueValueRootIndex); 21573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ subp(rax, rdx); 21583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Ret(); 2159f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 21603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ PopReturnAddressTo(tmp1); 21613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Push(left); 21623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Push(right); 21633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ PushReturnAddressFrom(tmp1); 2164f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ TailCallRuntime(Runtime::kStringCompare); 2165f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2167f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&miss); 2168f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateMiss(masm); 2169f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2172f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CompareICStub::GenerateReceivers(MacroAssembler* masm) { 2173f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK_EQ(CompareICState::RECEIVER, state()); 2174f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label miss; 2175f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Condition either_smi = masm->CheckEitherSmi(rdx, rax); 2176f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(either_smi, &miss, Label::kNear); 21773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2178f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 2179f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rcx); 2180f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(below, &miss, Label::kNear); 2181f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CmpObjectType(rdx, FIRST_JS_RECEIVER_TYPE, rcx); 2182f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(below, &miss, Label::kNear); 21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2184f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK_EQ(equal, GetCondition()); 2185f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ subp(rax, rdx); 21863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 2187f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2188f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&miss); 2189f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateMiss(masm); 21903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 21913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2193f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CompareICStub::GenerateKnownReceivers(MacroAssembler* masm) { 2194f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label miss; 2195f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Handle<WeakCell> cell = Map::WeakCellForMap(known_map_); 2196f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Condition either_smi = masm->CheckEitherSmi(rdx, rax); 2197f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(either_smi, &miss, Label::kNear); 21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2199f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ GetWeakValue(rdi, cell); 2200f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(FieldOperand(rdx, HeapObject::kMapOffset), rdi); 2201f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &miss, Label::kNear); 2202f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(FieldOperand(rax, HeapObject::kMapOffset), rdi); 2203f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_equal, &miss, Label::kNear); 22043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2205f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (Token::IsEqualityOp(op())) { 2206f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ subp(rax, rdx); 2207f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 2208f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 2209f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ PopReturnAddressTo(rcx); 2210f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(rdx); 2211f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(rax); 2212f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(Smi::FromInt(NegativeComparisonResult(GetCondition()))); 2213f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ PushReturnAddressFrom(rcx); 2214f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ TailCallRuntime(Runtime::kCompare); 2215f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 22163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2217f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&miss); 2218f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateMiss(masm); 2219f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 22203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2222f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid CompareICStub::GenerateMiss(MacroAssembler* masm) { 2223f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch { 2224f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Call the runtime system in a fresh internal frame. 2225f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 2226f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(rdx); 2227f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(rax); 2228f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(rdx); 2229f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(rax); 2230f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(Smi::FromInt(op())); 2231f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CallRuntime(Runtime::kCompareIC_Miss); 22323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2233f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compute the entry point of the rewritten stub. 2234f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(rdi, FieldOperand(rax, Code::kHeaderSize)); 2235f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(rax); 2236f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(rdx); 22373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2239f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Do a tail call to the rewritten stub. 2240f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(rdi); 2241f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 22423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2244f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, 2245f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label* miss, 2246f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label* done, 2247f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register properties, 2248f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Handle<Name> name, 2249f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register r0) { 2250f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(name->IsUniqueName()); 2251f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If names of slots in range from 1 to kProbes - 1 for the hash value are 2252f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // not equal to the name and kProbes-th slot is not used (its name is the 2253f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // undefined value), it guarantees the hash table doesn't contain the 2254f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // property. It's true even if some slots represent deleted properties 2255f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // (their names are the hole value). 2256f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch for (int i = 0; i < kInlinedProbes; i++) { 2257f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // r0 points to properties hash. 2258f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compute the masked index: (hash + i + i * i) & mask. 2259f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register index = r0; 2260f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Capacity is smi 2^n. 2261f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset)); 2262f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ decl(index); 2263f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ andp(index, 2264f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Immediate(name->Hash() + NameDictionary::GetProbeOffset(i))); 22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2266f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Scale the index by multiplying by the entry size. 2267f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(NameDictionary::kEntrySize == 3); 2268f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(index, Operand(index, index, times_2, 0)); // index *= 3. 22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2270f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register entity_name = r0; 2271f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Having undefined at this place means the name is not contained. 2272f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1); 2273f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(entity_name, Operand(properties, 2274f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch index, 2275f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch times_pointer_size, 2276f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch kElementsStartOffset - kHeapObjectTag)); 2277f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Cmp(entity_name, masm->isolate()->factory()->undefined_value()); 2278f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, done); 22793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2280f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Stop if found the property. 2281f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Cmp(entity_name, Handle<Name>(name)); 2282f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, miss); 22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2284f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label good; 2285f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check for the hole and skip. 2286f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex); 2287f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &good, Label::kNear); 22883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2289f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check if the entry name is not a unique name. 2290f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); 2291f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotUniqueNameInstanceType( 2292f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(entity_name, Map::kInstanceTypeOffset), miss); 2293f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&good); 22943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2296f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch NameDictionaryLookupStub stub(masm->isolate(), properties, r0, r0, 2297f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch NEGATIVE_LOOKUP); 2298f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(Handle<Object>(name)); 2299f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(Immediate(name->Hash())); 2300f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CallStub(&stub); 2301f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ testp(r0, r0); 2302f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(not_zero, miss); 2303f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(done); 2304f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 2305f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2306f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid NameDictionaryLookupStub::Generate(MacroAssembler* masm) { 2307f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // This stub overrides SometimesSetsUpAFrame() to return false. That means 2308f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // we cannot call anything that could cause a GC from this stub. 2309f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Stack frame on entry: 2310f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rsp[0 * kPointerSize] : return address. 2311f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rsp[1 * kPointerSize] : key's hash. 2312f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // rsp[2 * kPointerSize] : key. 2313f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Registers: 2314f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // dictionary_: NameDictionary to probe. 2315f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // result_: used as scratch. 2316f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // index_: will hold an index of entry if lookup is successful. 2317f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // might alias with result_. 2318f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Returns: 2319f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // result_ is zero if lookup failed, non zero otherwise. 2320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2321f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label in_dictionary, maybe_in_dictionary, not_in_dictionary; 2322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2323f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register scratch = result(); 2324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2325f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ SmiToInteger32(scratch, FieldOperand(dictionary(), kCapacityOffset)); 2326f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ decl(scratch); 2327f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(scratch); 2328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2329f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If names of slots in range from 1 to kProbes - 1 for the hash value are 2330f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // not equal to the name and kProbes-th slot is not used (its name is the 2331f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // undefined value), it guarantees the hash table doesn't contain the 2332f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // property. It's true even if some slots represent deleted properties 2333f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // (their names are the null value). 2334f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER, 2335f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch kPointerSize); 2336f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch for (int i = kInlinedProbes; i < kTotalProbes; i++) { 2337f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Compute the masked index: (hash + i + i * i) & mask. 2338f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(scratch, args.GetArgumentOperand(1)); 2339f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (i > 0) { 2340f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i))); 2341f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 2342f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ andp(scratch, Operand(rsp, 0)); 2343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2344f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Scale the index by multiplying by the entry size. 2345f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch STATIC_ASSERT(NameDictionary::kEntrySize == 3); 2346f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(index(), Operand(scratch, scratch, times_2, 0)); // index *= 3. 2347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2348f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Having undefined at this place means the name is not contained. 2349f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(scratch, Operand(dictionary(), index(), times_pointer_size, 2350f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch kElementsStartOffset - kHeapObjectTag)); 2351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2352f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Cmp(scratch, isolate()->factory()->undefined_value()); 2353f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, ¬_in_dictionary); 2354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2355f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Stop if found the property. 2356f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ cmpp(scratch, args.GetArgumentOperand(0)); 2357f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ j(equal, &in_dictionary); 2358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2359f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) { 2360f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If we hit a key that is not a unique name during negative 2361f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // lookup we have to bailout as this key might be equal to the 2362f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // key we are looking for. 2363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2364f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Check if the entry name is not a unique name. 2365f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 2366f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotUniqueNameInstanceType( 2367f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch FieldOperand(scratch, Map::kInstanceTypeOffset), 2368f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch &maybe_in_dictionary); 2369f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 2370f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 2371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2372f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&maybe_in_dictionary); 2373f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // If we are doing negative lookup then probing failure should be 2374f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // treated as a lookup success. For positive lookup probing failure 2375f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // should be treated as lookup failure. 2376f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (mode() == POSITIVE_LOOKUP) { 2377f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(scratch, Immediate(0)); 2378f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Drop(1); 2379f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(2 * kPointerSize); 2380f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 2381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2382f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&in_dictionary); 2383f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(scratch, Immediate(1)); 2384f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Drop(1); 2385f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(2 * kPointerSize); 2386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2387f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(¬_in_dictionary); 2388f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(scratch, Immediate(0)); 2389f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Drop(1); 2390f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(2 * kPointerSize); 2391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2394f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 2395f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Isolate* isolate) { 2396f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs); 2397f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch stub1.GetCode(); 2398f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch StoreBufferOverflowStub stub2(isolate, kSaveFPRegs); 2399f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch stub2.GetCode(); 2400f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 2401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2403f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch// Takes the input in 3 registers: address_ value_ and object_. A pointer to 2404f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch// the value has just been written into the object, now this stub makes sure 2405f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch// we keep the GC informed. The word in the object where the value has been 2406f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch// written is in the address register. 2407f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid RecordWriteStub::Generate(MacroAssembler* masm) { 2408f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label skip_to_incremental_noncompacting; 2409f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label skip_to_incremental_compacting; 2410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2411f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // The first two instructions are generated with labels so as to get the 2412f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // offset fixed up correctly by the bind(Label*) call. We patch it back and 2413f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // forth between a compare instructions (a nop in this position) and the 2414f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // real branch when we start and stop incremental heap marking. 2415f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // See RecordWriteStub::Patch for details. 2416f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&skip_to_incremental_noncompacting, Label::kNear); 2417f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(&skip_to_incremental_compacting, Label::kFar); 2418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2419f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (remembered_set_action() == EMIT_REMEMBERED_SET) { 2420f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 2421f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch MacroAssembler::kReturnAtEnd); 2422f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 2423f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 2424f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 2425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2426f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&skip_to_incremental_noncompacting); 2427f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateIncremental(masm, INCREMENTAL); 2428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2429f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&skip_to_incremental_compacting); 2430f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch GenerateIncremental(masm, INCREMENTAL_COMPACTION); 2431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2432f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. 2433f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Will be checked in IncrementalMarking::ActivateGeneratedStub. 2434f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm->set_byte_at(0, kTwoByteNopInstruction); 2435f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm->set_byte_at(2, kFiveByteNopInstruction); 2436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2439f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { 2440f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.Save(masm); 2441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2442f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (remembered_set_action() == EMIT_REMEMBERED_SET) { 2443f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label dont_need_remembered_set; 2444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2445f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(regs_.scratch0(), Operand(regs_.address(), 0)); 2446f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfNotInNewSpace(regs_.scratch0(), 2447f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.scratch0(), 2448f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch &dont_need_remembered_set); 2449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2450109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfInNewSpace(regs_.object(), regs_.scratch0(), 2451109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch &dont_need_remembered_set); 2452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2453f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // First notify the incremental marker if necessary, then update the 2454f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // remembered set. 2455f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CheckNeedsToInformIncrementalMarker( 2456f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); 2457f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch InformIncrementalMarker(masm); 2458f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.Restore(masm); 2459f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 2460f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch MacroAssembler::kReturnAtEnd); 2461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2462f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&dont_need_remembered_set); 2463f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 2464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2465f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CheckNeedsToInformIncrementalMarker( 2466f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm, kReturnOnNoNeedToInformIncrementalMarker, mode); 2467f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch InformIncrementalMarker(masm); 2468f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.Restore(masm); 2469f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 2470f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 2471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2473f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { 2474f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode()); 2475f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Register address = 2476f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch arg_reg_1.is(regs_.address()) ? kScratchRegister : regs_.address(); 2477f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(!address.is(regs_.object())); 2478f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch DCHECK(!address.is(arg_reg_1)); 2479f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(address, regs_.address()); 2480f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(arg_reg_1, regs_.object()); 2481f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // TODO(gc) Can we just set address arg2 in the beginning? 2482f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Move(arg_reg_2, address); 2483f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ LoadAddress(arg_reg_3, 2484f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference::isolate_address(isolate())); 2485f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch int argument_count = 3; 2486f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2487f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 2488f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ PrepareCallCFunction(argument_count); 2489f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CallCFunction( 2490f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch ExternalReference::incremental_marking_record_write_function(isolate()), 2491f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch argument_count); 2492f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode()); 2493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 249562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid RecordWriteStub::Activate(Code* code) { 249662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code); 249762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 2498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2499f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid RecordWriteStub::CheckNeedsToInformIncrementalMarker( 2500f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch MacroAssembler* masm, 2501f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch OnNoNeedToInformIncrementalMarker on_no_need, 2502f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Mode mode) { 2503f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label on_black; 2504f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label need_incremental; 2505f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label need_incremental_pop_object; 25068389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2507f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Let's look at the color of the object: If it is not black we don't have 2508f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // to inform the incremental marker. 2509f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfBlack(regs_.object(), 2510f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.scratch0(), 2511f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.scratch1(), 2512f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch &on_black, 2513f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label::kNear); 25148389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2515f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.Restore(masm); 2516f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 2517f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 2518f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch MacroAssembler::kReturnAtEnd); 2519f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 2520f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 2521f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 25228389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2523f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&on_black); 25248389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2525f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Get the value from the slot. 2526f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(regs_.scratch0(), Operand(regs_.address(), 0)); 25278389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2528f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (mode == INCREMENTAL_COMPACTION) { 2529f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label ensure_not_white; 25308389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2531f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CheckPageFlag(regs_.scratch0(), // Contains value. 2532f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.scratch1(), // Scratch. 2533f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch MemoryChunk::kEvacuationCandidateMask, 2534f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch zero, 2535f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch &ensure_not_white, 2536f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch Label::kNear); 25378389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2538f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CheckPageFlag(regs_.object(), 2539f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.scratch1(), // Scratch. 2540f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch MemoryChunk::kSkipEvacuationSlotsRecordingMask, 2541f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch zero, 2542f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch &need_incremental); 25438389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2544f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&ensure_not_white); 2545f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 25468389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2547f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // We need an extra register for this, so we push the object register 2548f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // temporarily. 2549f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Push(regs_.object()); 2550f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ JumpIfWhite(regs_.scratch0(), // The value. 2551f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.scratch1(), // Scratch. 2552f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.object(), // Scratch. 2553f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch &need_incremental_pop_object, Label::kNear); 2554f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(regs_.object()); 25558389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2556f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch regs_.Restore(masm); 2557f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 2558f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 2559f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch MacroAssembler::kReturnAtEnd); 2560f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } else { 2561f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ ret(0); 2562f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch } 25638389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2564f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&need_incremental_pop_object); 2565f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Pop(regs_.object()); 25668389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2567f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ bind(&need_incremental); 25688389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2569f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch // Fall through when we need to inform the incremental marker. 2570f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 25718389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2572f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2573f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdochvoid StubFailureTrampolineStub::Generate(MacroAssembler* masm) { 2574f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch CEntryStub ces(isolate(), 1, kSaveFPRegs); 2575f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); 2576f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch int parameter_count_offset = 25773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch StubFailureTrampolineFrameConstants::kArgumentsLengthOffset; 2578f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ movp(rbx, MemOperand(rbp, parameter_count_offset)); 2579f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); 2580f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ PopReturnAddressTo(rcx); 2581f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch int additional_offset = 2582f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch function_mode() == JS_FUNCTION_STUB_MODE ? kPointerSize : 0; 2583f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ leap(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); 2584f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ jmp(rcx); // Return to IC Miss stub, continuation still on stack. 25858389745919cae02139ddc085a63c00d024269cf2Ben Murdoch} 25868389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2587109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2588109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { 2589109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (masm->isolate()->function_entry_hook() != NULL) { 2590109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ProfileEntryHookStub stub(masm->isolate()); 2591109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch masm->CallStub(&stub); 2592109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2593109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2594109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2595109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2596109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ProfileEntryHookStub::Generate(MacroAssembler* masm) { 2597109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // This stub can be called from essentially anywhere, so it needs to save 2598109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // all volatile and callee-save registers. 2599109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const size_t kNumSavedRegisters = 2; 2600109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ pushq(arg_reg_1); 2601109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ pushq(arg_reg_2); 2602109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2603109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Calculate the original stack pointer and store it in the second arg. 2604109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ leap(arg_reg_2, 2605109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Operand(rsp, kNumSavedRegisters * kRegisterSize + kPCOnStackSize)); 2606109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Calculate the function address to the first arg. 2608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(arg_reg_1, Operand(rsp, kNumSavedRegisters * kRegisterSize)); 2609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ subp(arg_reg_1, Immediate(Assembler::kShortCallInstructionLength)); 2610109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Save the remainder of the volatile registers. 2612109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch masm->PushCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2); 2613109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2614109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Call the entry hook function. 2615109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Move(rax, FUNCTION_ADDR(isolate()->function_entry_hook()), 2616109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Assembler::RelocInfoNone()); 2617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2618109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AllowExternalCallThatCantCauseGC scope(masm); 2619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2620109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kArgumentCount = 2; 2621109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ PrepareCallCFunction(kArgumentCount); 2622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallCFunction(rax, kArgumentCount); 2623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2624109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Restore volatile regs. 2625109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch masm->PopCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2); 2626109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ popq(arg_reg_2); 2627109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ popq(arg_reg_1); 2628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 2630f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 2631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2633109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochtemplate<class T> 2634109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void CreateArrayDispatch(MacroAssembler* masm, 2635109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AllocationSiteOverrideMode mode) { 2636109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (mode == DISABLE_ALLOCATION_SITES) { 2637109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub(masm->isolate(), GetInitialFastElementsKind(), mode); 2638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub); 2639109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (mode == DONT_OVERRIDE) { 2640109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int last_index = GetSequenceIndexFromFastElementsKind( 2641109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch TERMINAL_FAST_ELEMENTS_KIND); 2642109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i <= last_index; ++i) { 2643109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label next; 2644109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 2645109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpl(rdx, Immediate(kind)); 2646109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &next); 2647109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub(masm->isolate(), kind); 2648109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub); 2649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&next); 2650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2651109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If we reached this point there is a problem. 2653109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Abort(kUnexpectedElementsKindInArrayConstructor); 2654109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 2655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch UNREACHABLE(); 2656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void CreateArrayDispatchOneArgument(MacroAssembler* masm, 2661109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AllocationSiteOverrideMode mode) { 2662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rbx - allocation site (if mode != DISABLE_ALLOCATION_SITES) 2663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rdx - kind (if mode != DISABLE_ALLOCATION_SITES) 2664109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rax - number of arguments 2665109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rdi - constructor? 2666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rsp[0] - return address 2667109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // rsp[8] - last argument 2668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2669109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label normal_sequence; 2670109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (mode == DONT_OVERRIDE) { 2671109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 2672109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 2673109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_ELEMENTS == 2); 2674109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); 2675109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_DOUBLE_ELEMENTS == 4); 2676109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); 2677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2678109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // is the low bit set? If so, we are holey and that is good. 2679109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ testb(rdx, Immediate(1)); 2680109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_zero, &normal_sequence); 2681109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2683109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // look at the first argument 2684109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); 2685109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rcx, args.GetArgumentOperand(0)); 2686109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ testp(rcx, rcx); 2687109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(zero, &normal_sequence); 2688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2689109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (mode == DISABLE_ALLOCATION_SITES) { 2690109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind initial = GetInitialFastElementsKind(); 2691109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind holey_initial = GetHoleyElementsKind(initial); 2692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2693109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArraySingleArgumentConstructorStub stub_holey(masm->isolate(), 2694109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch holey_initial, 2695109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DISABLE_ALLOCATION_SITES); 2696109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub_holey); 2697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2698109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&normal_sequence); 2699109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArraySingleArgumentConstructorStub stub(masm->isolate(), 2700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch initial, 2701109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DISABLE_ALLOCATION_SITES); 2702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub); 2703109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (mode == DONT_OVERRIDE) { 2704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We are going to create a holey array, but our kind is non-holey. 2705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Fix kind and retry (only if we have an allocation site in the slot). 2706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ incl(rdx); 2707f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 2709109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Map> allocation_site_map = 2710109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch masm->isolate()->factory()->allocation_site_map(); 2711109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Cmp(FieldOperand(rbx, 0), allocation_site_map); 2712109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(equal, kExpectedAllocationSite); 2713109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2715109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Save the resulting elements kind in type info. We can't just store r3 2716109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // in the AllocationSite::transition_info field because elements kind is 2717109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // restricted to a portion of the field...upper bits need to be left alone. 2718109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 2719109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiAddConstant(FieldOperand(rbx, AllocationSite::kTransitionInfoOffset), 2720109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Smi::FromInt(kFastElementsKindPackedToHoley)); 2721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2722109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&normal_sequence); 2723109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int last_index = GetSequenceIndexFromFastElementsKind( 2724109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch TERMINAL_FAST_ELEMENTS_KIND); 2725109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i <= last_index; ++i) { 2726109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label next; 2727109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 2728109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpl(rdx, Immediate(kind)); 2729109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &next); 2730109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArraySingleArgumentConstructorStub stub(masm->isolate(), kind); 2731109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub); 2732109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&next); 2733109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2734109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2735109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If we reached this point there is a problem. 2736109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Abort(kUnexpectedElementsKindInArrayConstructor); 2737109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 2738109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch UNREACHABLE(); 2739109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2743109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochtemplate<class T> 2744109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { 2745109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int to_index = GetSequenceIndexFromFastElementsKind( 2746109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch TERMINAL_FAST_ELEMENTS_KIND); 2747109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i <= to_index; ++i) { 2748109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 2749109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub(isolate, kind); 2750109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stub.GetCode(); 2751109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { 2752109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch T stub1(isolate, kind, DISABLE_ALLOCATION_SITES); 2753109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stub1.GetCode(); 2754109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2755109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2756f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 275813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) { 2759109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( 2760109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch isolate); 2761109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( 2762109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch isolate); 276313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ArrayNArgumentsConstructorStub stub(isolate); 276413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch stub.GetCode(); 2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2766109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS }; 2767109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (int i = 0; i < 2; i++) { 2768109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // For internal arrays we only need a few things 2769109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]); 2770109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stubh1.GetCode(); 2771109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]); 2772109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stubh2.GetCode(); 2773109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2774109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2776109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ArrayConstructorStub::GenerateDispatchToArrayStub( 2777c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch MacroAssembler* masm, AllocationSiteOverrideMode mode) { 2778c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label not_zero_case, not_one_case; 2779c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ testp(rax, rax); 2780c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ j(not_zero, ¬_zero_case); 2781c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 2782c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2783c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ bind(¬_zero_case); 2784c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ cmpl(rax, Immediate(1)); 2785c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ j(greater, ¬_one_case); 2786c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CreateArrayDispatchOneArgument(masm, mode); 2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2788c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ bind(¬_one_case); 2789c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ArrayNArgumentsConstructorStub stub(masm->isolate()); 2790c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ TailCallStub(&stub); 2791c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2793109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ArrayConstructorStub::Generate(MacroAssembler* masm) { 2794109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 2795109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- rax : argc 2796109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- rbx : AllocationSite or undefined 2797109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- rdi : constructor 2798109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- rdx : new target 2799109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- rsp[0] : return address 2800109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- rsp[8] : last argument 2801109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 2802109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 2803109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The array construct code is only set for the global and natives 2804109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // builtin Array functions which always have maps. 2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2806109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Initial map for the builtin Array function should be a map. 2807109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 2808109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Will both indicate a NULL and a Smi. 2809109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 2810109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); 2811109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); 2812109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpObjectType(rcx, MAP_TYPE, rcx); 2813109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Check(equal, kUnexpectedInitialMapForArrayFunction); 2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2815109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We should either have undefined in rbx or a valid AllocationSite 2816109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ AssertUndefinedOrAllocationSite(rbx); 2817109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2819109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Enter the context of the Array function. 2820109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2822109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label subclassing; 2823109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpp(rdi, rdx); 2824109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &subclassing); 2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label no_info; 2827109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If the feedback vector is the undefined value call an array constructor 2828109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // that doesn't use AllocationSites. 2829109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 2830109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, &no_info); 2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2832109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Only look at the lower 16 bits of the transition info. 2833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rdx, FieldOperand(rbx, AllocationSite::kTransitionInfoOffset)); 2834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiToInteger32(rdx, rdx); 2835109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 2836109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ andp(rdx, Immediate(AllocationSite::ElementsKindBits::kMask)); 2837109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); 2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2839109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&no_info); 2840109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); 2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2842109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Subclassing 2843109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&subclassing); 2844c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StackArgumentsAccessor args(rsp, rax); 2845c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ movp(args.GetReceiverOperand(), rdi); 2846c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ addp(rax, Immediate(3)); 2847109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ PopReturnAddressTo(rcx); 2848109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(rdx); 2849109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(rbx); 2850109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ PushReturnAddressFrom(rcx); 2851109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpToExternalReference(ExternalReference(Runtime::kNewArray, isolate())); 2852f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 28548389745919cae02139ddc085a63c00d024269cf2Ben Murdoch 2855109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InternalArrayConstructorStub::GenerateCase( 2856109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MacroAssembler* masm, ElementsKind kind) { 2857109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label not_zero_case, not_one_case; 2858109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label normal_sequence; 2859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2860109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ testp(rax, rax); 2861109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_zero, ¬_zero_case); 2862109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArrayNoArgumentConstructorStub stub0(isolate(), kind); 2863109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub0); 2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2865109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(¬_zero_case); 2866109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpl(rax, Immediate(1)); 2867109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(greater, ¬_one_case); 2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2869109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (IsFastPackedElementsKind(kind)) { 2870109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // We might need to create a holey array 2871109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // look at the first argument 2872109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); 2873109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rcx, args.GetArgumentOperand(0)); 2874109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ testp(rcx, rcx); 2875109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(zero, &normal_sequence); 2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2877109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArraySingleArgumentConstructorStub 2878109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch stub1_holey(isolate(), GetHoleyElementsKind(kind)); 2879109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub1_holey); 2880109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2881f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2882109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&normal_sequence); 2883109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch InternalArraySingleArgumentConstructorStub stub1(isolate(), kind); 2884109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stub1); 2885f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2886109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(¬_one_case); 288713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ArrayNArgumentsConstructorStub stubN(isolate()); 2888109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ TailCallStub(&stubN); 2889109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2890f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2891f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2892109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InternalArrayConstructorStub::Generate(MacroAssembler* masm) { 2893109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 2894109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- rax : argc 2895109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- rdi : constructor 2896109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- rsp[0] : return address 2897109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- rsp[8] : last argument 2898109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 2899f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2900109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 2901109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The array construct code is only set for the global and natives 2902109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // builtin Array functions which always have maps. 2903f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2904109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Initial map for the builtin Array function should be a map. 2905109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 2906109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Will both indicate a NULL and a Smi. 2907109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 2908109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); 2909109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); 2910109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpObjectType(rcx, MAP_TYPE, rcx); 2911109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Check(equal, kUnexpectedInitialMapForArrayFunction); 2912109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2914109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Figure out the right elements kind 2915109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2917109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load the map's "bit field 2" into |result|. We only need the first byte, 2918109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // but the following masking takes care of that anyway. 2919109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movzxbp(rcx, FieldOperand(rcx, Map::kBitField2Offset)); 2920109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Retrieve elements_kind from bit field 2. 2921109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ DecodeField<Map::ElementsKindBits>(rcx); 2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2923109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 2924109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label done; 2925109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpl(rcx, Immediate(FAST_ELEMENTS)); 2926109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, &done); 2927109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpl(rcx, Immediate(FAST_HOLEY_ELEMENTS)); 2928109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(equal, 2929109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kInvalidElementsKindForInternalArrayOrInternalPackedArray); 2930109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done); 2931109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2933109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label fast_elements_case; 2934109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpl(rcx, Immediate(FAST_ELEMENTS)); 2935109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, &fast_elements_case); 2936109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateCase(masm, FAST_HOLEY_ELEMENTS); 2937f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 2938109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&fast_elements_case); 2939109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateCase(masm, FAST_ELEMENTS); 2940f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 2941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic int Offset(ExternalReference ref0, ExternalReference ref1) { 2943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int64_t offset = (ref0.address() - ref1.address()); 2944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check that fits into int. 2945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(static_cast<int>(offset) == offset); 2946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<int>(offset); 2947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Prepares stack to put arguments (aligns and so on). WIN64 calling 2950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// convention requires to put the pointer to the return value slot into 2951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// rcx (rcx must be preserverd until CallApiFunctionAndReturn). Saves 2952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// context (rsi). Clobbers rax. Allocates arg_stack_space * kPointerSize 2953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// inside the exit frame (not GCed) accessible via StackSpaceOperand. 2954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void PrepareCallApiFunction(MacroAssembler* masm, int arg_stack_space) { 2955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ EnterApiExitFrame(arg_stack_space); 2956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Calls an API function. Allocates HandleScope, extracts returned value 2960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// from handle and propagates exceptions. Clobbers r14, r15, rbx and 2961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// caller-save registers. Restores context. On return removes 2962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// stack_space * kPointerSize (GCed). 2963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void CallApiFunctionAndReturn(MacroAssembler* masm, 2964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register function_address, 2965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference thunk_ref, 2966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register thunk_last_arg, int stack_space, 2967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Operand* stack_space_operand, 2968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Operand return_value_operand, 2969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Operand* context_restore_operand) { 2970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label prologue; 2971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label promote_scheduled_exception; 2972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label delete_allocated_handles; 2973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label leave_exit_frame; 2974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label write_back; 2975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate* isolate = masm->isolate(); 2977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Factory* factory = isolate->factory(); 2978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference next_address = 2979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::handle_scope_next_address(isolate); 2980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kNextOffset = 0; 2981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kLimitOffset = Offset( 2982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::handle_scope_limit_address(isolate), next_address); 2983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kLevelOffset = Offset( 2984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::handle_scope_level_address(isolate), next_address); 2985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference scheduled_exception_address = 2986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::scheduled_exception_address(isolate); 2987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(rdx.is(function_address) || r8.is(function_address)); 2989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Allocate HandleScope in callee-save registers. 2990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register prev_next_address_reg = r14; 2991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register prev_limit_reg = rbx; 2992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register base_reg = r15; 2993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(base_reg, next_address); 2994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(prev_next_address_reg, Operand(base_reg, kNextOffset)); 2995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(prev_limit_reg, Operand(base_reg, kLimitOffset)); 2996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addl(Operand(base_reg, kLevelOffset), Immediate(1)); 2997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_log_timer_events) { 2999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope frame(masm, StackFrame::MANUAL); 3000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushSafepointRegisters(); 3001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PrepareCallCFunction(1); 3002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate)); 3003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallCFunction(ExternalReference::log_enter_external_function(isolate), 3004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1); 3005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopSafepointRegisters(); 3006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label profiler_disabled; 3009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label end_profiler_check; 3010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(rax, ExternalReference::is_profiling_address(isolate)); 3011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpb(Operand(rax, 0), Immediate(0)); 3012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &profiler_disabled); 3013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Third parameter is the address of the actual getter function. 3015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(thunk_last_arg, function_address); 3016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(rax, thunk_ref); 3017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&end_profiler_check); 3018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&profiler_disabled); 3020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the api function! 3021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(rax, function_address); 3022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&end_profiler_check); 3024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the api function! 3026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ call(rax); 3027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_log_timer_events) { 3029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope frame(masm, StackFrame::MANUAL); 3030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushSafepointRegisters(); 3031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PrepareCallCFunction(1); 3032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate)); 3033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallCFunction(ExternalReference::log_leave_external_function(isolate), 3034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1); 3035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopSafepointRegisters(); 3036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the value from ReturnValue 3039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rax, return_value_operand); 3040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&prologue); 3041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // No more valid handles (the result handle was the last one). Restore 3043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // previous handle scope. 3044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ subl(Operand(base_reg, kLevelOffset), Immediate(1)); 3045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(Operand(base_reg, kNextOffset), prev_next_address_reg); 3046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpp(prev_limit_reg, Operand(base_reg, kLimitOffset)); 3047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &delete_allocated_handles); 3048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Leave the API exit frame. 3050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&leave_exit_frame); 3051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool restore_context = context_restore_operand != NULL; 3052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (restore_context) { 3053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rsi, *context_restore_operand); 3054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (stack_space_operand != nullptr) { 3056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rbx, *stack_space_operand); 3057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LeaveApiExitFrame(!restore_context); 3059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if the function scheduled an exception. 3061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(rdi, scheduled_exception_address); 3062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Cmp(Operand(rdi, 0), factory->the_hole_value()); 3063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &promote_scheduled_exception); 3064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if DEBUG 3066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if the function returned a valid JavaScript value. 3067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label ok; 3068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register return_value = rax; 3069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register map = rcx; 3070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(return_value, &ok, Label::kNear); 3072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(map, FieldOperand(return_value, HeapObject::kMapOffset)); 3073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(map, LAST_NAME_TYPE); 3075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below_equal, &ok, Label::kNear); 3076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE); 3078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(above_equal, &ok, Label::kNear); 3079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); 3081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &ok, Label::kNear); 3082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(return_value, Heap::kUndefinedValueRootIndex); 3084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &ok, Label::kNear); 3085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(return_value, Heap::kTrueValueRootIndex); 3087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &ok, Label::kNear); 3088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(return_value, Heap::kFalseValueRootIndex); 3090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &ok, Label::kNear); 3091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(return_value, Heap::kNullValueRootIndex); 3093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &ok, Label::kNear); 3094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Abort(kAPICallReturnedInvalidObject); 3096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&ok); 3098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif 3099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (stack_space_operand != nullptr) { 3101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(stack_space, 0); 3102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(rcx); 3103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addq(rsp, rbx); 3104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(rcx); 3105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 3106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ret(stack_space * kPointerSize); 3107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Re-throw by promoting a scheduled exception. 3110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&promote_scheduled_exception); 3111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kPromoteScheduledException); 3112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // HandleScope limit has changed. Delete allocated extensions. 3114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&delete_allocated_handles); 3115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(Operand(base_reg, kLimitOffset), prev_limit_reg); 3116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(prev_limit_reg, rax); 3117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate)); 3118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAddress(rax, 3119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::delete_handle_scope_extensions(isolate)); 3120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ call(rax); 3121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rax, prev_limit_reg); 3122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&leave_exit_frame); 3123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 31253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid CallApiCallbackStub::Generate(MacroAssembler* masm) { 3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 3127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- rdi : callee 3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rbx : call_data 3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rcx : holder 3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rdx : api_function_address 3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsi : context 3132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- rax : number of arguments if argc is a register 3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[0] : return address 3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[8] : last argument 3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- ... 3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[argc * 8] : first argument 3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- rsp[(argc + 1) * 8] : receiver 3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register callee = rdi; 3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register call_data = rbx; 3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder = rcx; 3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register api_function_address = rdx; 3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register context = rsi; 3145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register return_address = r8; 3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef FunctionCallbackArguments FCA; 3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kContextSaveIndex == 6); 3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kCalleeIndex == 5); 3151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kDataIndex == 4); 3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kReturnValueOffset == 3); 3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 3154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kIsolateIndex == 1); 3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FCA::kHolderIndex == 0); 3156bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(FCA::kNewTargetIndex == 7); 3157bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(FCA::kArgsLength == 8); 3158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(return_address); 3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3161bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // new target 3162bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 3163bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context save 3165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(context); 3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // callee 3168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(callee); 3169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // call data 3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(call_data); 3172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = call_data; 31733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (!this->call_data_undefined()) { 3174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // return value 3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch); 3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // return value default 3179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch); 3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // isolate 3181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(scratch, ExternalReference::isolate_address(masm->isolate())); 3182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch); 3183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // holder 3184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(holder); 3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, rsp); 3187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push return address back on stack. 3188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushReturnAddressFrom(return_address); 3189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 31903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (!this->is_lazy()) { 3191109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // load context from callee 3192109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(context, FieldOperand(callee, JSFunction::kContextOffset)); 3193109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate the v8::Arguments structure in the arguments' space since 3196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // it's not controlled by GC. 3197bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch const int kApiStackSpace = 3; 3198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PrepareCallApiFunction(masm, kApiStackSpace); 3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FunctionCallbackInfo::implicit_args_. 32023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch int argc = this->argc(); 3203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(StackSpaceOperand(0), scratch); 32043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ addp(scratch, Immediate((argc + FCA::kArgsLength - 1) * kPointerSize)); 32053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // FunctionCallbackInfo::values_. 32063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ movp(StackSpaceOperand(1), scratch); 32073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // FunctionCallbackInfo::length_. 32083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Set(StackSpaceOperand(2), argc); 3209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(__MINGW64__) || defined(_WIN64) 3211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register arguments_arg = rcx; 3212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register callback_arg = rdx; 3213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 3214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register arguments_arg = rdi; 3215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register callback_arg = rsi; 3216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 3217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's okay if api_function_address == callback_arg 3219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // but not arguments_arg 3220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!api_function_address.is(arguments_arg)); 3221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // v8::InvocationCallback's argument. 3223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(arguments_arg, StackSpaceOperand(0)); 3224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference thunk_ref = 3226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::invoke_function_callback(masm->isolate()); 3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Accessor for FunctionCallbackInfo and first js arg. 3229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength + 1, 3230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ARGUMENTS_DONT_CONTAIN_RECEIVER); 3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand context_restore_operand = args_from_rbp.GetArgumentOperand( 3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FCA::kArgsLength - FCA::kContextSaveIndex); 3233bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Operand length_operand = StackSpaceOperand(2); 3234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand return_value_operand = args_from_rbp.GetArgumentOperand( 32353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch this->is_store() ? 0 : FCA::kArgsLength - FCA::kReturnValueOffset); 3236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int stack_space = 0; 3237bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Operand* stack_space_operand = &length_operand; 32383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch stack_space = argc + FCA::kArgsLength + 1; 32393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch stack_space_operand = nullptr; 3240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, callback_arg, 3241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stack_space, stack_space_operand, 3242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return_value_operand, &context_restore_operand); 3243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallApiGetterStub::Generate(MacroAssembler* masm) { 3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(__MINGW64__) || defined(_WIN64) 3248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register getter_arg = r8; 3249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register accessor_info_arg = rdx; 3250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name_arg = rcx; 3251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 3252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register getter_arg = rdx; 3253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register accessor_info_arg = rsi; 3254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name_arg = rdi; 3255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 3256bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register api_function_address = r8; 3257bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register receiver = ApiGetterDescriptor::ReceiverRegister(); 3258bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register holder = ApiGetterDescriptor::HolderRegister(); 3259bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register callback = ApiGetterDescriptor::CallbackRegister(); 3260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = rax; 3261bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!AreAliased(receiver, holder, callback, scratch)); 3262bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3263bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Build v8::PropertyCallbackInfo::args_ array on the stack and push property 3264bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // name below the exit frame to make GC aware of them. 3265bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0); 3266bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1); 3267bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2); 3268bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3); 3269bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4); 3270bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5); 3271bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6); 3272bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7); 3273bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3274bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Insert additional parameters into the stack frame above return address. 3275bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PopReturnAddressTo(scratch); 3276bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(receiver); 3277bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(FieldOperand(callback, AccessorInfo::kDataOffset)); 3278bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 3279bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(kScratchRegister); // return value 3280bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(kScratchRegister); // return value default 3281bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushAddress(ExternalReference::isolate_address(isolate())); 3282bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(holder); 3283c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Push(Smi::kZero); // should_throw_on_error -> false 3284bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(FieldOperand(callback, AccessorInfo::kNameOffset)); 3285bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushReturnAddressFrom(scratch); 3286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3287109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // v8::PropertyCallbackInfo::args_ array and name handle. 3288109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; 3289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3290109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Allocate v8::PropertyCallbackInfo in non-GCed stack space. 3291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kArgStackSpace = 1; 3292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3293109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load address of v8::PropertyAccessorInfo::args_ array. 3294109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ leap(scratch, Operand(rsp, 2 * kPointerSize)); 3295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PrepareCallApiFunction(masm, kArgStackSpace); 3297109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Create v8::PropertyCallbackInfo object on the stack and initialize 3298109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // it's args_ field. 3299109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Operand info_object = StackSpaceOperand(0); 3300109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(info_object, scratch); 3301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ leap(name_arg, Operand(scratch, -kPointerSize)); 3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The context register (rsi) has been saved in PrepareCallApiFunction and 3304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // could be used to pass arguments. 3305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ leap(accessor_info_arg, info_object); 3306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference thunk_ref = 3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::invoke_accessor_getter_callback(isolate()); 3309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's okay if api_function_address == getter_arg 3311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // but not accessor_info_arg or name_arg 3312bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!api_function_address.is(accessor_info_arg)); 3313bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!api_function_address.is(name_arg)); 3314bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ movp(scratch, FieldOperand(callback, AccessorInfo::kJsGetterOffset)); 3315bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ movp(api_function_address, 3316bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch FieldOperand(scratch, Foreign::kForeignAddressOffset)); 3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3318109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // +3 is to skip prolog, return address and name handle. 3319109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Operand return_value_operand( 3320109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch rbp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize); 3321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, getter_arg, 3322109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch kStackUnwindSpace, nullptr, return_value_operand, 3323109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch NULL); 3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 332680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#undef __ 332780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 3329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 333080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 333180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif // V8_TARGET_ARCH_X64 3332