1864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Copyright 2012 the V8 project authors. All rights reserved. 2864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be 3864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// found in the LICENSE file. 4864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h" 6864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 7864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#if V8_TARGET_ARCH_X87 8864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 99aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org#include "src/base/bits.h" 10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/bootstrapper.h" 11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/code-stubs.h" 124b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/codegen.h" 13fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org#include "src/ic/handler-compiler.h" 14a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org#include "src/ic/ic.h" 15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/isolate.h" 16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/jsregexp.h" 17196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/regexp-macro-assembler.h" 18196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/runtime.h" 19864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 20864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace v8 { 21864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace internal { 22864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 23864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 24864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void InitializeArrayConstructorDescriptor( 25b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Isolate* isolate, CodeStubDescriptor* descriptor, 26864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int constant_stack_parameter_count) { 27864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // register state 28864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax -- number of arguments 29864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi -- function 30864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx -- allocation site with elements kind 3147390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org Address deopt_handler = Runtime::FunctionForId( 3247390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org Runtime::kArrayConstructor)->entry; 33864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 34864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (constant_stack_parameter_count == 0) { 35b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org descriptor->Initialize(deopt_handler, constant_stack_parameter_count, 3647390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org JS_FUNCTION_STUB_MODE); 37864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 38b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org descriptor->Initialize(eax, deopt_handler, constant_stack_parameter_count, 397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); 40864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 41864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 42864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 43864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 44864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void InitializeInternalArrayConstructorDescriptor( 45b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Isolate* isolate, CodeStubDescriptor* descriptor, 46864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int constant_stack_parameter_count) { 47864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // register state 48864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax -- number of arguments 49864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi -- constructor function 5047390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org Address deopt_handler = Runtime::FunctionForId( 5147390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org Runtime::kInternalArrayConstructor)->entry; 52864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 53864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (constant_stack_parameter_count == 0) { 54b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org descriptor->Initialize(deopt_handler, constant_stack_parameter_count, 5547390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org JS_FUNCTION_STUB_MODE); 56864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 57b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org descriptor->Initialize(eax, deopt_handler, constant_stack_parameter_count, 587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); 59864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 60864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 61864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 62864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 63b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid ArrayNoArgumentConstructorStub::InitializeDescriptor( 64b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org CodeStubDescriptor* descriptor) { 65b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org InitializeArrayConstructorDescriptor(isolate(), descriptor, 0); 66864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 67864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 68864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 69b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid ArraySingleArgumentConstructorStub::InitializeDescriptor( 70b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org CodeStubDescriptor* descriptor) { 71b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org InitializeArrayConstructorDescriptor(isolate(), descriptor, 1); 72864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 73864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 74864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 75b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid ArrayNArgumentsConstructorStub::InitializeDescriptor( 76b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org CodeStubDescriptor* descriptor) { 77b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org InitializeArrayConstructorDescriptor(isolate(), descriptor, -1); 78864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 79864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 80864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 81b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid InternalArrayNoArgumentConstructorStub::InitializeDescriptor( 82b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org CodeStubDescriptor* descriptor) { 83b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0); 84864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 85864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 86864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 87b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid InternalArraySingleArgumentConstructorStub::InitializeDescriptor( 88b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org CodeStubDescriptor* descriptor) { 89b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1); 90864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 91864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 92864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 93b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid InternalArrayNArgumentsConstructorStub::InitializeDescriptor( 94b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org CodeStubDescriptor* descriptor) { 95b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1); 96864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 97864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 98864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 99864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#define __ ACCESS_MASM(masm) 100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 102b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm, 103b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org ExternalReference miss) { 104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Update the static counter each time a new code stub is generated. 105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate()->counters()->code_stubs()->Increment(); 106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 107b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor(); 1086313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org int param_count = descriptor.GetEnvironmentParameterCount(); 109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org { 110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Call the runtime system in a fresh internal frame. 111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 112e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(param_count == 0 || 1136313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org eax.is(descriptor.GetEnvironmentParameterRegister(param_count - 1))); 114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Push arguments 115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org for (int i = 0; i < param_count; ++i) { 1166313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org __ push(descriptor.GetEnvironmentParameterRegister(i)); 117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 118474e8b19cf12dc057572a8543864dd6586ee0a65machenbach@chromium.org __ CallExternalReference(miss, param_count); 119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We don't allow a GC during a store buffer overflow so there is no need to 127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // store the registers in any particular way, but we do have to store and 128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // restore them. 129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pushad(); 13006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org if (save_doubles()) { 13106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org // Save FPU stat in m108byte. 13206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ sub(esp, Immediate(108)); 13306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ fnsave(Operand(esp, 0)); 13406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org } 135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org const int argument_count = 1; 136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org AllowExternalCallThatCantCauseGC scope(masm); 138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ PrepareCallCFunction(argument_count, ecx); 139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 0 * kPointerSize), 140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(ExternalReference::isolate_address(isolate()))); 141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CallCFunction( 142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference::store_buffer_overflow_function(isolate()), 143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org argument_count); 14406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org if (save_doubles()) { 14506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org // Restore FPU stat in m108byte. 14606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ frstor(Operand(esp, 0)); 14706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ add(esp, Immediate(108)); 14806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org } 149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ popad(); 150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgclass FloatingPointHelper : public AllStatic { 155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org public: 156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org enum ArgLocation { 157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ARGS_ON_STACK, 158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ARGS_IN_REGISTERS 159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org }; 160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Code pattern for loading a floating point value. Input value must 162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // be either a smi or a heap number object (fp value). Requirements: 163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // operand in register number. Returns operand as floating point number 164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // on FPU stack. 165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static void LoadFloatOperand(MacroAssembler* masm, Register number); 166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Test if operands are smi or number objects (fp). Requirements: 168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // operand_1 in eax, operand_2 in edx; falls through on float 169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // operands, jumps to the non_float label otherwise. 170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static void CheckFloatOperands(MacroAssembler* masm, 171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* non_float, 172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch); 173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}; 174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid DoubleToIStub::Generate(MacroAssembler* masm) { 177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register input_reg = this->source(); 178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register final_result_reg = this->destination(); 179e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(is_truncating()); 180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label check_negative, process_64_bits, done, done_no_stash; 182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int double_offset = offset(); 184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Account for return address and saved regs if input is esp. 186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (input_reg.is(esp)) double_offset += 3 * kPointerSize; 187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MemOperand mantissa_operand(MemOperand(input_reg, double_offset)); 189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MemOperand exponent_operand(MemOperand(input_reg, 190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org double_offset + kDoubleSize / 2)); 191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch1; 193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org { 194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch_candidates[3] = { ebx, edx, edi }; 195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org for (int i = 0; i < 3; i++) { 196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org scratch1 = scratch_candidates[i]; 197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!final_result_reg.is(scratch1) && !input_reg.is(scratch1)) break; 198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Since we must use ecx for shifts below, use some other register (eax) 201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // to calculate the result if ecx is the requested return register. 202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register result_reg = final_result_reg.is(ecx) ? eax : final_result_reg; 203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Save ecx if it isn't the return register and therefore volatile, or if it 204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // is the return register, then save the temp register we use in its stead for 205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // the result. 206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register save_reg = final_result_reg.is(ecx) ? eax : ecx; 207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(scratch1); 208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(save_reg); 209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org bool stash_exponent_copy = !input_reg.is(esp); 211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch1, mantissa_operand); 212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, exponent_operand); 213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (stash_exponent_copy) __ push(ecx); 214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(ecx, HeapNumber::kExponentMask); 216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ shr(ecx, HeapNumber::kExponentShift); 217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(result_reg, MemOperand(ecx, -HeapNumber::kExponentBias)); 218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(result_reg, Immediate(HeapNumber::kMantissaBits)); 219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(below, &process_64_bits); 220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Result is entirely in lower 32-bits of mantissa 222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize; 223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(ecx, Immediate(delta)); 224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ xor_(result_reg, result_reg); 225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, Immediate(31)); 226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above, &done); 227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ shl_cl(scratch1); 228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&check_negative); 229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&process_64_bits); 231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Result must be extracted from shifted 32-bit mantissa 232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(ecx, Immediate(delta)); 233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ neg(ecx); 234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (stash_exponent_copy) { 235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(result_reg, MemOperand(esp, 0)); 236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(result_reg, exponent_operand); 238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(result_reg, 240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32))); 241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(result_reg, 242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32))); 243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ shrd(result_reg, scratch1); 244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ shr_cl(result_reg); 245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, Immediate(32)); 246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org { 247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label skip_mov; 248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &skip_mov, Label::kNear); 249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch1, result_reg); 250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&skip_mov); 251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If the double was negative, negate the integer result. 254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&check_negative); 255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(result_reg, scratch1); 256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ neg(result_reg); 257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (stash_exponent_copy) { 258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(MemOperand(esp, 0), Immediate(0)); 259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(exponent_operand, Immediate(0)); 261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org { 263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label skip_mov; 264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(less_equal, &skip_mov, Label::kNear); 265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(result_reg, scratch1); 266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&skip_mov); 267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Restore registers 270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (stash_exponent_copy) { 272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(esp, Immediate(kDoubleSize / 2)); 273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done_no_stash); 275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!final_result_reg.is(result_reg)) { 276e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(final_result_reg.is(ecx)); 277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(final_result_reg, result_reg); 278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(save_reg); 280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(scratch1); 281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, 286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register number) { 287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label load_smi, done; 288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(number, &load_smi, Label::kNear); 290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); 291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&done, Label::kNear); 292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&load_smi); 294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(number); 295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(number); 296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ fild_s(Operand(esp, 0)); 297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(number); 298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, 304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* non_float, 305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch) { 306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label test_other, done; 307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Test if both operands are floats or smi -> scratch=k_is_float; 308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Otherwise scratch = k_not_float. 309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(edx, &test_other, Label::kNear); 310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); 311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Factory* factory = masm->isolate()->factory(); 312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(scratch, factory->heap_number_map()); 313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, non_float); // argument in edx is not a number -> NaN 314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&test_other); 316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(eax, &done, Label::kNear); 317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); 318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(scratch, factory->heap_number_map()); 319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, non_float); // argument in eax is not a number -> NaN 320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Fall-through: Both operands are numbers. 322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MathPowStub::Generate(MacroAssembler* masm) { 327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // No SSE2 support 328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org UNREACHABLE(); 329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FunctionPrototypeStub::Generate(MacroAssembler* masm) { 333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label miss; 33442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org Register receiver = LoadDescriptor::ReceiverRegister(); 335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3362b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, eax, 3372b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org ebx, &miss); 338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 3392b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org PropertyAccessCompiler::TailCallBuiltin( 3402b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC)); 341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 344a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgvoid LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { 345a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org // Return address is on the stack. 346a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org Label slow; 347a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 348a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org Register receiver = LoadDescriptor::ReceiverRegister(); 349a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org Register key = LoadDescriptor::NameRegister(); 350a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org Register scratch = eax; 351a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org DCHECK(!scratch.is(receiver) && !scratch.is(key)); 352a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 353a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org // Check that the key is an array index, that is Uint32. 354a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ test(key, Immediate(kSmiTagMask | kSmiSignMask)); 355a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ j(not_zero, &slow); 356a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 357a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org // Everything is fine, call runtime. 358a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ pop(scratch); 359a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ push(receiver); // receiver 360a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ push(key); // key 361a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ push(scratch); // return address 362a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 363a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org // Perform tail call to the entry. 364a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org ExternalReference ref = ExternalReference( 365a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org IC_Utility(IC::kLoadElementWithInterceptor), masm->isolate()); 366a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ TailCallExternalReference(ref, 2, 1); 367a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 368a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ bind(&slow); 369a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org PropertyAccessCompiler::TailCallBuiltin( 370a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); 371a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org} 372a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 373a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The key is in edx and the parameter count is in eax. 376b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org DCHECK(edx.is(ArgumentsAccessReadDescriptor::index())); 377b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org DCHECK(eax.is(ArgumentsAccessReadDescriptor::parameter_count())); 378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The displacement is used for skipping the frame pointer on the 380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // stack. It is the offset of the last parameter (if any) relative 381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // to the frame pointer. 382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kDisplacement = 1 * kPointerSize; 383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the key is a smi. 385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label slow; 386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(edx, &slow, Label::kNear); 387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check if the calling frame is an arguments adaptor frame. 389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label adaptor; 390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset)); 392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &adaptor, Label::kNear); 394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check index against formal parameters count limit passed in 396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // through register eax. Use unsigned comparison to get negative 397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // check for free. 398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edx, eax); 399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above_equal, &slow, Label::kNear); 400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Read the argument from the stack and return it. 402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTagSize == 1); 403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these. 404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(ebx, Operand(ebp, eax, times_2, 0)); 405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ neg(edx); 406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); 407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Arguments adaptor case: Check index against actual arguments 410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // limit found in the arguments adaptor frame. Use unsigned 411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // comparison to get negative check for free. 412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&adaptor); 413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edx, ecx); 415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above_equal, &slow, Label::kNear); 416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Read the argument from the stack and return it. 418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTagSize == 1); 419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these. 420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(ebx, Operand(ebx, ecx, times_2, 0)); 421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ neg(edx); 422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); 423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Slow-case: Handle non-smi or out-of-bounds access to arguments 426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // by calling the runtime system. 427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&slow); 428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ebx); // Return address. 429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); 430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ebx); 431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); 432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { 436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0] : return address 437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[4] : number of parameters 438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[8] : receiver displacement 439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[12] : function 440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check if the calling frame is an arguments adaptor frame. 442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label runtime; 443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); 445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &runtime, Label::kNear); 447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Patch the arguments.length and the parameters pointer. 449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 1 * kPointerSize), ecx); 451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(edx, Operand(edx, ecx, times_2, 452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org StandardFrameConstants::kCallerSPOffset)); 453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 2 * kPointerSize), edx); 454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&runtime); 45647390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); 457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { 461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0] : return address 462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[4] : number of parameters (tagged) 463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[8] : receiver displacement 464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[12] : function 465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx = parameter count (tagged) 467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, Operand(esp, 1 * kPointerSize)); 468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check if the calling frame is an arguments adaptor frame. 470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // TODO(rossberg): Factor out some of the bits that are shared with the other 471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Generate* functions. 472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label runtime; 473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label adaptor_frame, try_allocate; 474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); 476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &adaptor_frame, Label::kNear); 478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // No adaptor, parameter count = argument count. 480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, ebx); 481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&try_allocate, Label::kNear); 482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We have an adaptor frame. Patch the parameters pointer. 484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&adaptor_frame); 485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(edx, Operand(edx, ecx, times_2, 487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org StandardFrameConstants::kCallerSPOffset)); 488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 2 * kPointerSize), edx); 489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx = parameter count (tagged) 49160fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org // ecx = argument count (smi-tagged) 492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[4] = parameter count (tagged) 493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[8] = address of receiver argument 494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compute the mapped parameter count = min(ebx, ecx) in ebx. 495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ebx, ecx); 496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(less_equal, &try_allocate, Label::kNear); 497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, ecx); 498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&try_allocate); 500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Save mapped parameter count. 502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ebx); 503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compute the sizes of backing store, parameter map, and arguments object. 505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // 1. Parameter map, has 2 extra words containing context and backing store. 506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org const int kParameterMapHeaderSize = 507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArray::kHeaderSize + 2 * kPointerSize; 508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label no_parameter_map; 509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ebx, ebx); 510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &no_parameter_map, Label::kNear); 511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize)); 512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&no_parameter_map); 513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // 2. Backing store. 515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); 516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // 3. Arguments object. 518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(ebx, Immediate(Heap::kSloppyArgumentsObjectSize)); 519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Do the allocation of all three objects in one go. 521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Allocate(ebx, eax, edx, edi, &runtime, TAG_OBJECT); 522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax = address of new object(s) (tagged) 52460fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org // ecx = argument count (smi-tagged) 525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0] = mapped parameter count (tagged) 526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[8] = parameter count (tagged) 527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[12] = address of receiver argument 52860fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org // Get the arguments map from the current native context into edi. 52960fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org Label has_mapped_parameters, instantiate; 530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, FieldOperand(edi, GlobalObject::kNativeContextOffset)); 532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, Operand(esp, 0 * kPointerSize)); 533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ebx, ebx); 534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &has_mapped_parameters, Label::kNear); 53560fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ mov( 53660fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org edi, 53760fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org Operand(edi, Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX))); 53860fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ jmp(&instantiate, Label::kNear); 539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&has_mapped_parameters); 54160fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ mov( 54260fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org edi, 54360fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org Operand(edi, Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX))); 54460fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ bind(&instantiate); 545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax = address of new object (tagged) 547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx = mapped parameter count (tagged) 54860fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org // ecx = argument count (smi-tagged) 54960fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org // edi = address of arguments map (tagged) 550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0] = mapped parameter count (tagged) 551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[8] = parameter count (tagged) 552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[12] = address of receiver argument 553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Copy the JS object part. 55460fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); 55560fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), 55660fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org masm->isolate()->factory()->empty_fixed_array()); 55760fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ mov(FieldOperand(eax, JSObject::kElementsOffset), 55860fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org masm->isolate()->factory()->empty_fixed_array()); 559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Set up the callee in-object property. 561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); 562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Operand(esp, 4 * kPointerSize)); 56360fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ AssertNotSmi(edx); 564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(eax, JSObject::kHeaderSize + 565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Heap::kArgumentsCalleeIndex * kPointerSize), 566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org edx); 567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Use the length (smi tagged) and set that as an in-object property too. 56960fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ AssertSmi(ecx); 570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(eax, JSObject::kHeaderSize + 572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Heap::kArgumentsLengthIndex * kPointerSize), 573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ecx); 574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Set up the elements pointer in the allocated arguments object. 576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If we allocated a parameter map, edi will point there, otherwise to the 577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // backing store. 578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(edi, Operand(eax, Heap::kSloppyArgumentsObjectSize)); 579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); 580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax = address of new object (tagged) 582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx = mapped parameter count (tagged) 583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx = argument count (tagged) 584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi = address of parameter map or backing store (tagged) 585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0] = mapped parameter count (tagged) 586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[8] = parameter count (tagged) 587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[12] = address of receiver argument 588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Free a register. 589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(eax); 590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Initialize parameter map. If there are no mapped arguments, we're done. 592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label skip_parameter_map; 593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ebx, ebx); 594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &skip_parameter_map); 595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edi, FixedArray::kMapOffset), 597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(isolate()->factory()->sloppy_arguments_elements_map())); 598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2)))); 599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax); 600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi); 601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(eax, Operand(edi, ebx, times_2, kParameterMapHeaderSize)); 602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 1 * kPointerSize), eax); 603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Copy the parameter slots and the holes in the arguments. 605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We need to fill in mapped_parameter_count slots. They index the context, 606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // where parameters are stored in reverse order, at 607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The mapped parameter thus need to get indices 609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // MIN_CONTEXT_SLOTS+parameter_count-1 .. 610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count 611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We loop from right to left. 612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label parameters_loop, parameters_test; 613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ecx); 614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, 2 * kPointerSize)); 615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); 616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(ebx, Operand(esp, 4 * kPointerSize)); 617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(ebx, eax); 618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, isolate()->factory()->the_hole_value()); 619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, edi); 620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(edi, Operand(edi, eax, times_2, kParameterMapHeaderSize)); 621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax = loop variable (tagged) 622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx = mapping index (tagged) 623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx = the hole value 624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx = address of parameter map (tagged) 625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi = address of backing store (tagged) 626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0] = argument count (tagged) 627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[4] = address of new object (tagged) 628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[8] = mapped parameter count (tagged) 629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[16] = parameter count (tagged) 630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[20] = address of receiver argument 631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(¶meters_test, Label::kNear); 632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¶meters_loop); 634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(eax, Immediate(Smi::FromInt(1))); 635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edx, eax, times_2, kParameterMapHeaderSize), ebx); 636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edi, eax, times_2, FixedArray::kHeaderSize), ecx); 637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(ebx, Immediate(Smi::FromInt(1))); 638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¶meters_test); 639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(eax, eax); 640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, ¶meters_loop, Label::kNear); 641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ecx); 642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&skip_parameter_map); 644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx = argument count (tagged) 646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi = address of backing store (tagged) 647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0] = address of new object (tagged) 648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[4] = mapped parameter count (tagged) 649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[12] = parameter count (tagged) 650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[16] = address of receiver argument 651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Copy arguments header and remaining slots (if there are any). 652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edi, FixedArray::kMapOffset), 653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(isolate()->factory()->fixed_array_map())); 654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); 655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label arguments_loop, arguments_test; 657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, Operand(esp, 1 * kPointerSize)); 658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Operand(esp, 4 * kPointerSize)); 659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(edx, ebx); // Is there a smarter way to do negative scaling? 660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(edx, ebx); 661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&arguments_test, Label::kNear); 662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&arguments_loop); 664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(edx, Immediate(kPointerSize)); 665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(edx, 0)); 666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edi, ebx, times_2, FixedArray::kHeaderSize), eax); 667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(ebx, Immediate(Smi::FromInt(1))); 668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&arguments_test); 670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ebx, ecx); 671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(less, &arguments_loop, Label::kNear); 672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Restore. 674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(eax); // Address of arguments object. 675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ebx); // Parameter count. 676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Return and remove the on-stack parameters. 678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(3 * kPointerSize); 679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Do the runtime call to allocate the arguments object. 681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&runtime); 682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(eax); // Remove saved parameter count. 683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 1 * kPointerSize), ecx); // Patch argument count. 68447390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); 685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { 689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0] : return address 690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[4] : number of parameters 691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[8] : receiver displacement 692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[12] : function 693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check if the calling frame is an arguments adaptor frame. 695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label adaptor_frame, try_allocate, runtime; 696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); 698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &adaptor_frame, Label::kNear); 700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get the length from the frame. 702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(esp, 1 * kPointerSize)); 703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&try_allocate, Label::kNear); 704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Patch the arguments.length and the parameters pointer. 706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&adaptor_frame); 707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 1 * kPointerSize), ecx); 709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(edx, Operand(edx, ecx, times_2, 710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org StandardFrameConstants::kCallerSPOffset)); 711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 2 * kPointerSize), edx); 712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Try the new space allocation. Start out with computing the size of 714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // the arguments object and the elements array. 715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label add_arguments_object; 716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&try_allocate); 717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, ecx); 718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &add_arguments_object, Label::kNear); 719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize)); 720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&add_arguments_object); 721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(ecx, Immediate(Heap::kStrictArgumentsObjectSize)); 722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Do the allocation of both objects in one go. 724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Allocate(ecx, eax, edx, ebx, &runtime, TAG_OBJECT); 725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 72660fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org // Get the arguments map from the current native context. 727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, FieldOperand(edi, GlobalObject::kNativeContextOffset)); 72960fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org const int offset = Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX); 730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, Operand(edi, offset)); 731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 73260fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); 73360fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), 73460fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org masm->isolate()->factory()->empty_fixed_array()); 73560fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ mov(FieldOperand(eax, JSObject::kElementsOffset), 73660fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org masm->isolate()->factory()->empty_fixed_array()); 737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get the length (smi tagged) and set that as an in-object property too. 739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(esp, 1 * kPointerSize)); 74160fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org __ AssertSmi(ecx); 742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(eax, JSObject::kHeaderSize + 743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Heap::kArgumentsLengthIndex * kPointerSize), 744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ecx); 745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If there are no actual arguments, we're done. 747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label done; 748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, ecx); 749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &done, Label::kNear); 750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get the parameters pointer from the stack. 752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Operand(esp, 2 * kPointerSize)); 753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Set up the elements pointer in the allocated arguments object and 755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // initialize the header in the elements fixed array. 756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(edi, Operand(eax, Heap::kStrictArgumentsObjectSize)); 757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); 758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edi, FixedArray::kMapOffset), 759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(isolate()->factory()->fixed_array_map())); 760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); 762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Untag the length for the loop below. 763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(ecx); 764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Copy the fixed array slots. 766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label loop; 767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&loop); 768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. 769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); 770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(edi, Immediate(kPointerSize)); 771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(edx, Immediate(kPointerSize)); 772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ dec(ecx); 773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &loop); 774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Return and remove the on-stack parameters. 776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(3 * kPointerSize); 778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Do the runtime call to allocate the arguments object. 780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&runtime); 78147390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1); 782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid RegExpExecStub::Generate(MacroAssembler* masm) { 786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Just jump directly to runtime if native RegExp is not selected at compile 787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // time or if regexp entry in generated code is turned off runtime switch or 788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // at compilation. 789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef V8_INTERPRETED_REGEXP 790248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1); 791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#else // V8_INTERPRETED_REGEXP 792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Stack frame on entry. 794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0]: return address 795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[4]: last_match_info (expected JSArray) 796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[8]: previous index 797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[12]: subject string 798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[16]: JSRegExp object 799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kLastMatchInfoOffset = 1 * kPointerSize; 801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kPreviousIndexOffset = 2 * kPointerSize; 802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kSubjectOffset = 3 * kPointerSize; 803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kJSRegExpOffset = 4 * kPointerSize; 804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label runtime; 806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Factory* factory = isolate()->factory(); 807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Ensure that a RegExp stack is allocated. 809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference address_of_regexp_stack_memory_address = 810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference::address_of_regexp_stack_memory_address(isolate()); 811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference address_of_regexp_stack_memory_size = 812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference::address_of_regexp_stack_memory_size(isolate()); 813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); 814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ebx, ebx); 815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &runtime); 816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the first argument is a JSRegExp object. 818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, kJSRegExpOffset)); 819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(eax, &runtime); 821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); 822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &runtime); 823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the RegExp has been compiled (data contains a fixed array). 825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); 826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, Immediate(kSmiTagMask)); 828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Check(not_zero, kUnexpectedTypeForRegExpDataFixedArrayExpected); 829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx); 830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected); 831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: RegExp data (FixedArray) 834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset)); 836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ebx, Immediate(Smi::FromInt(JSRegExp::IRREGEXP))); 837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &runtime); 838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: RegExp data (FixedArray) 840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the number of captures fit in the static offsets vector buffer. 841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); 842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check (number_of_captures + 1) * 2 <= offsets vector size 843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Or number_of_captures * 2 <= offsets vector size - 2 844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Multiplying by 2 comes for free since edx is smi-tagged. 845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); 848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edx, Isolate::kJSRegexpStaticOffsetsVectorSize - 2); 849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above, &runtime); 850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Reset offset for possibly sliced string. 852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(edi, Immediate(0)); 853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, kSubjectOffset)); 854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(eax, &runtime); 855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, eax); // Make a copy of the original subject string. 856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: subject string 860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: subject string 861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: subject string instance type 862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: RegExp data (FixedArray) 863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Handle subject string according to its encoding and representation: 864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (1) Sequential two byte? If yes, go to (9). 865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (2) Sequential one byte? If yes, go to (6). 866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (3) Anything but sequential or cons? If yes, go to (7). 867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (4) Cons string. If the string is flat, replace subject with first string. 868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Otherwise bailout. 869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (5a) Is subject sequential two byte? If yes, go to (9). 870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (5b) Is subject external? If yes, go to (8). 871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (6) One byte sequential. Load regexp code for one byte. 872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (E) Carry on. 873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org /// [...] 874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Deferred code at the end of the stub: 876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (7) Not a long external string? If yes, go to (10). 877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (8) External string. Make it, offset-wise, look like a sequential string. 878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (8a) Is the external string one byte? If yes, go to (6). 879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (9) Two byte sequential. Load regexp code for one byte. Go to (E). 880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (10) Short external string or not a string? If yes, bail out to runtime. 881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (11) Sliced string. Replace subject with parent. Go to (5a). 882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */, 884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org external_string /* 8 */, check_underlying /* 5a */, 885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org not_seq_nor_cons /* 7 */, check_code /* E */, 886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org not_long_external /* 10 */; 887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (1) Sequential two byte? If yes, go to (9). 889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(ebx, kIsNotStringMask | 890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kStringRepresentationMask | 891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kStringEncodingMask | 892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kShortExternalStringMask); 893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); 894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &seq_two_byte_string); // Go to (9). 895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (2) Sequential one byte? If yes, go to (6). 897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Any other sequential string must be one byte. 898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(ebx, Immediate(kIsNotStringMask | 899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kStringRepresentationMask | 900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kShortExternalStringMask)); 901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6). 902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (3) Anything but sequential or cons? If yes, go to (7). 904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We check whether the subject string is a cons, since sequential strings 905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // have already been covered. 906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kConsStringTag < kExternalStringTag); 907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ebx, Immediate(kExternalStringTag)); 911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(greater_equal, ¬_seq_nor_cons); // Go to (7). 912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (4) Cons string. Check that it's flat. 914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Replace subject with first string and reload instance type. 915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string()); 916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &runtime); 917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); 918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&check_underlying); 919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (5a) Is subject sequential two byte? If yes, go to (9). 923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(ebx, kStringRepresentationMask | kStringEncodingMask); 924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); 925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &seq_two_byte_string); // Go to (9). 926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (5b) Is subject external? If yes, go to (8). 927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(ebx, kStringRepresentationMask); 928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The underlying external string is never a short external string. 929d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); 930d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); 931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &external_string); // Go to (8). 932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: sequential subject string (or look-alike, external string) 934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: original subject string 935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: RegExp data (FixedArray) 936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (6) One byte sequential. Load regexp code for one byte. 937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&seq_one_byte_string); 938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load previous index and check range before edx is overwritten. We have 939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // to use edx instead of eax here because it might have been only made to 940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // look like a sequential string when it actually is an external string. 941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, Operand(esp, kPreviousIndexOffset)); 942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(ebx, &runtime); 943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); 944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above_equal, &runtime); 945b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org __ mov(edx, FieldOperand(ecx, JSRegExp::kDataOneByteCodeOffset)); 946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(ecx, Immediate(1)); // Type is one byte. 947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (E) Carry on. String handling is done. 949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&check_code); 950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: irregexp code 951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the irregexp code has been generated for the actual string 952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // encoding. If it has, the field contains a code object otherwise it contains 953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // a smi (code flushing support). 954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(edx, &runtime); 955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: subject string 957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: previous index (smi) 958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: code 959b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org // ecx: encoding of subject string (1 if one_byte, 0 if two_byte); 960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // All checks done. Now push arguments for native regexp code. 961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Counters* counters = isolate()->counters(); 962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ IncrementCounter(counters->regexp_entry_native(), 1); 963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Isolates: note we add an additional parameter here (isolate pointer). 965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kRegExpExecuteArguments = 9; 966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ EnterApiExitFrame(kRegExpExecuteArguments); 967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Argument 9: Pass current isolate address. 969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 8 * kPointerSize), 970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(ExternalReference::isolate_address(isolate()))); 971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Argument 8: Indicate that this is a direct call from JavaScript. 973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 7 * kPointerSize), Immediate(1)); 974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Argument 7: Start (high end) of backtracking stack memory area. 976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(esi, Operand::StaticVariable(address_of_regexp_stack_memory_address)); 977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(esi, Operand::StaticVariable(address_of_regexp_stack_memory_size)); 978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 6 * kPointerSize), esi); 979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Argument 6: Set the number of capture registers to zero to force global 981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // regexps to behave as non-global. This does not affect non-global regexps. 982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 5 * kPointerSize), Immediate(0)); 983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Argument 5: static offsets vector buffer. 985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 4 * kPointerSize), 986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(ExternalReference::address_of_static_offsets_vector( 987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate()))); 988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Argument 2: Previous index. 990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(ebx); 991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 1 * kPointerSize), ebx); 992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Argument 1: Original subject string. 994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The original subject is in the previous stack frame. Therefore we have to 995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // use ebp, which points exactly to one pointer size below the previous esp. 996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (Because creating a new stack frame pushes the previous ebp onto the stack 997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // and thereby moves up esp by one kPointerSize.) 998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize)); 999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 0 * kPointerSize), esi); 1000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esi: original subject string 1002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: underlying subject string 1003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: previous index 1004b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org // ecx: encoding of subject string (1 if one_byte 0 if two_byte); 1005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: code 1006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Argument 4: End of string data 1007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Argument 3: Start of string data 1008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Prepare start and end index of the input. 1009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load the length from the original sliced string if that is the case. 1010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(esi, FieldOperand(esi, String::kLengthOffset)); 1011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(esi, edi); // Calculate input end wrt offset. 1012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(edi); 1013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(ebx, edi); // Calculate input start wrt offset. 1014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: start index of the input string 1016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esi: end index of the input string 1017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label setup_two_byte, setup_rest; 1018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, ecx); 1019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &setup_two_byte, Label::kNear); 1020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(esi); 1021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(ecx, FieldOperand(eax, esi, times_1, SeqOneByteString::kHeaderSize)); 1022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. 1023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqOneByteString::kHeaderSize)); 1024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. 1025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&setup_rest, Label::kNear); 1026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&setup_two_byte); 1028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 1029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTagSize == 1); // esi is smi (powered by 2). 1030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(ecx, FieldOperand(eax, esi, times_1, SeqTwoByteString::kHeaderSize)); 1031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. 1032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); 1033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. 1034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&setup_rest); 1036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Locate the code entry and call it. 1038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag)); 1039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ call(edx); 1040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Drop arguments and come back to JS mode. 1042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ LeaveApiExitFrame(true); 1043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check the result. 1045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label success; 1046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, 1); 1047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We expect exactly one result since we force the called regexp to behave 1048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // as non-global. 1049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &success); 1050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label failure; 1051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, NativeRegExpMacroAssembler::FAILURE); 1052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &failure); 1053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION); 1054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If not exception it can only be retry. Handle that in the runtime system. 1055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &runtime); 1056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Result must now be exception. If there is no pending exception already a 1057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // stack overflow (on the backtrack stack) was detected in RegExp code but 1058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // haven't created the exception yet. Handle that in the runtime system. 1059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // TODO(592): Rerunning the RegExp to get the stack overflow exception. 1060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference pending_exception(Isolate::kPendingExceptionAddress, 1061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate()); 1062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Immediate(isolate()->factory()->the_hole_value())); 1063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand::StaticVariable(pending_exception)); 1064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edx, eax); 1065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &runtime); 1066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // For exception, throw the exception again. 1067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Clear the pending exception variable. 1069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand::StaticVariable(pending_exception), edx); 1070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Special handling of termination exceptions which are uncatchable 1072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // by javascript code. 1073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, factory->termination_exception()); 1074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label throw_termination_exception; 1075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &throw_termination_exception, Label::kNear); 1076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Handle normal exception by following handler chain. 1078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Throw(eax); 1079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&throw_termination_exception); 1081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ThrowUncatchable(eax); 1082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&failure); 1084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // For failure to match, return null. 1085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, factory->null_value()); 1086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(4 * kPointerSize); 1087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load RegExp data. 1089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&success); 1090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, kJSRegExpOffset)); 1091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); 1092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); 1093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Calculate number of capture registers (number_of_captures + 1) * 2. 1094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 1095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 1096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(edx, Immediate(2)); // edx was a smi. 1097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: Number of capture registers 1099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load last_match_info which is still known to be a fast case JSArray. 1100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the fourth object is a JSArray object. 1101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, kLastMatchInfoOffset)); 1102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(eax, &runtime); 1103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); 1104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &runtime); 1105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the JSArray is in fast case. 1106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); 1107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset)); 1108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, factory->fixed_array_map()); 1109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &runtime); 1110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the last match info has space for the capture registers and the 1111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // additional information. 1112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset)); 1113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(eax); 1114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(eax, Immediate(RegExpImpl::kLastMatchOverhead)); 1115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edx, eax); 1116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(greater, &runtime); 1117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: last_match_info backing store (FixedArray) 1119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: number of capture registers 1120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Store the capture count. 1121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiTag(edx); // Number of capture registers to smi. 1122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(ebx, RegExpImpl::kLastCaptureCountOffset), edx); 1123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(edx); // Number of capture registers back from smi. 1124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Store last subject and last input. 1125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, kSubjectOffset)); 1126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, eax); 1127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(ebx, RegExpImpl::kLastSubjectOffset), eax); 112806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ RecordWriteField(ebx, RegExpImpl::kLastSubjectOffset, eax, edi, 112906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org kDontSaveFPRegs); 1130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, ecx); 1131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(ebx, RegExpImpl::kLastInputOffset), eax); 113206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ RecordWriteField(ebx, RegExpImpl::kLastInputOffset, eax, edi, 113306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org kDontSaveFPRegs); 1134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get the static offsets vector filled by the native regexp code. 1136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference address_of_static_offsets_vector = 1137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference::address_of_static_offsets_vector(isolate()); 1138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Immediate(address_of_static_offsets_vector)); 1139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: last_match_info backing store (FixedArray) 1141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: offsets vector 1142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: number of capture registers 1143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label next_capture, done; 1144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Capture register counter starts from number of capture registers and 1145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // counts down until wraping after zero. 1146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&next_capture); 1147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(edx, Immediate(1)); 1148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(negative, &done, Label::kNear); 1149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Read the value from the static offsets vector buffer. 1150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, Operand(ecx, edx, times_int_size, 0)); 1151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiTag(edi); 1152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Store the smi value in the last match info. 1153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(ebx, 1154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org edx, 1155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org times_pointer_size, 1156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org RegExpImpl::kFirstCaptureOffset), 1157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org edi); 1158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&next_capture); 1159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 1160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Return last match info. 1162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, kLastMatchInfoOffset)); 1163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(4 * kPointerSize); 1164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Do the runtime call to execute the regexp. 1166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&runtime); 116747390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1); 1168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Deferred code for string handling. 1170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (7) Not a long external string? If yes, go to (10). 1171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_seq_nor_cons); 1172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compare flags are still set from (3). 1173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(greater, ¬_long_external, Label::kNear); // Go to (10). 1174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (8) External string. Short external strings have been ruled out. 1176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&external_string); 1177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Reload instance type. 1178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 1179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 1181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Assert that we do not have a cons or slice (indirect strings) here. 1182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Sequential strings have already been ruled out. 1183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(ebx, kIsIndirectStringMask); 1184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(zero, kExternalStringExpectedButNotFound); 1185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); 1187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Move the pointer so that offset-wise, it looks like a sequential string. 1188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 1189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 1190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kTwoByteStringTag == 0); 1191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (8a) Is the external string one byte? If yes, go to (6). 1192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(ebx, kStringEncodingMask); 1193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &seq_one_byte_string); // Goto (6). 1194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: sequential subject string (or look-alike, external string) 1196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: original subject string 1197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: RegExp data (FixedArray) 1198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (9) Two byte sequential. Load regexp code for one byte. Go to (E). 1199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&seq_two_byte_string); 1200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load previous index and check range before edx is overwritten. We have 1201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // to use edx instead of eax here because it might have been only made to 1202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // look like a sequential string when it actually is an external string. 1203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, Operand(esp, kPreviousIndexOffset)); 1204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(ebx, &runtime); 1205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); 1206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above_equal, &runtime); 1207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); 1208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(ecx, Immediate(0)); // Type is two byte. 1209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&check_code); // Go to (E). 1210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (10) Not a string or a short external string? If yes, bail out to runtime. 1212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_long_external); 1213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Catch non-string subject or short external string. 1214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); 1215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag)); 1216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &runtime); 1217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (11) Sliced string. Replace subject with parent. Go to (5a). 1219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load offset into edi and replace subject string with parent. 1220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset)); 1221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, FieldOperand(eax, SlicedString::kParentOffset)); 1222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&check_underlying); // Go to (5a). 1223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif // V8_INTERPRETED_REGEXP 1224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic int NegativeComparisonResult(Condition cc) { 1228e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(cc != equal); 1229e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((cc == less) || (cc == less_equal) 1230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org || (cc == greater) || (cc == greater_equal)); 1231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org return (cc == greater || cc == greater_equal) ? LESS : GREATER; 1232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1235a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgstatic void CheckInputType(MacroAssembler* masm, Register input, 1236a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org CompareICState::State expected, Label* fail) { 1237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label ok; 1238a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org if (expected == CompareICState::SMI) { 1239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(input, fail); 1240a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org } else if (expected == CompareICState::NUMBER) { 1241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(input, &ok); 1242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(FieldOperand(input, HeapObject::kMapOffset), 1243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(masm->isolate()->factory()->heap_number_map())); 1244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, fail); 1245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We could be strict about internalized/non-internalized here, but as long as 1247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // hydrogen doesn't care, the stub doesn't have to care either. 1248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&ok); 1249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void BranchIfNotInternalizedString(MacroAssembler* masm, 1253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* label, 1254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register object, 1255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch) { 1256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(object, label); 1257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); 1258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 1259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 1260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); 1261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, label); 1262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 126542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.orgvoid CompareICStub::GenerateGeneric(MacroAssembler* masm) { 1266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label check_unequal_objects; 1267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Condition cc = GetCondition(); 1268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label miss; 127021d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org CheckInputType(masm, edx, left(), &miss); 127121d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org CheckInputType(masm, eax, right(), &miss); 1272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compare two smis. 1274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label non_smi, smi_done; 1275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, edx); 1276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ or_(ecx, eax); 1277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(ecx, &non_smi, Label::kNear); 1278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(edx, eax); // Return on the result of the subtraction. 1279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(no_overflow, &smi_done, Label::kNear); 1280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ not_(edx); // Correct sign in case of overflow. edx is never 0 here. 1281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&smi_done); 1282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, edx); 1283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 1284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&non_smi); 1285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // NOTICE! This code is only reached after a smi-fast-case check, so 1287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // it is certain that at least one operand isn't a smi. 1288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Identical objects can be compared fast, but there are some tricky cases 1290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // for NaN and undefined. 1291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label generic_heap_number_comparison; 1292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org { 1293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label not_identical; 1294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, edx); 1295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, ¬_identical); 1296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (cc != equal) { 1298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check for undefined. undefined OP undefined is false even though 1299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // undefined == undefined. 1300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label check_for_nan; 1301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edx, isolate()->factory()->undefined_value()); 1302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &check_for_nan, Label::kNear); 1303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); 1304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 1305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&check_for_nan); 1306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Test for NaN. Compare heap numbers in a general way, 1309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // to hanlde NaNs correctly. 1310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 1311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(isolate()->factory()->heap_number_map())); 1312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &generic_heap_number_comparison, Label::kNear); 1313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (cc != equal) { 1314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Call runtime on identical JSObjects. Otherwise return equal. 1315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 1316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above_equal, ¬_identical); 1317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(EQUAL))); 1319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 1320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_identical); 1323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Strict equality can quickly decide whether objects are equal. 1326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Non-strict object equality is slower, so it is handled later in the stub. 1327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (cc == equal && strict()) { 1328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label slow; // Fallthrough label. 1329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label not_smis; 1330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If we're doing a strict equality comparison, we don't have to do 1331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // type conversion, so we generate code to do fast comparison for objects 1332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // and oddballs. Non-smi numbers and strings still go through the usual 1333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // slow-case code. 1334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If either is a Smi (we know that not both are), then they can only 1335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // be equal if the other is a HeapNumber. If so, use the slow case. 1336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 1337e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(0, Smi::FromInt(0)); 1338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Immediate(kSmiTagMask)); 1339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(ecx, eax); 1340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, edx); 1341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, ¬_smis, Label::kNear); 1342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // One operand is a smi. 1343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check whether the non-smi is a heap number. 1345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTagMask == 1); 1346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx still holds eax & kSmiTag, which is either zero or one. 1347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(ecx, Immediate(0x01)); 1348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, edx); 1349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ xor_(ebx, eax); 1350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(ebx, ecx); // ebx holds either 0 or eax ^ edx. 1351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ xor_(ebx, eax); 1352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // if eax was smi, ebx is now edx, else eax. 1353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check if the non-smi operand is a heap number. 1355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 1356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(isolate()->factory()->heap_number_map())); 1357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If heap number, handle it in the slow case. 1358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &slow, Label::kNear); 1359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Return non-equal (ebx is not zero) 1360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, ebx); 1361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 1362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_smis); 1364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If either operand is a JSObject or an oddball value, then they are not 1365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // equal since their pointers are different 1366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // There is no test for undetectability in strict equality. 1367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get the type of the first operand. 1369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If the first object is a JS object, we have done pointer comparison. 1370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label first_non_object; 1371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); 1372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 1373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(below, &first_non_object, Label::kNear); 1374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Return non-zero (eax is not zero) 1376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label return_not_equal; 1377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kHeapObjectTag != 0); 1378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&return_not_equal); 1379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 1380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&first_non_object); 1382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check for oddballs: true, false, null, undefined. 1383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpInstanceType(ecx, ODDBALL_TYPE); 1384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &return_not_equal); 1385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(edx, FIRST_SPEC_OBJECT_TYPE, ecx); 1387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above_equal, &return_not_equal); 1388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check for oddballs: true, false, null, undefined. 1390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpInstanceType(ecx, ODDBALL_TYPE); 1391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &return_not_equal); 1392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Fall through to the general case. 1394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&slow); 1395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Generate the number comparison code. 1398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label non_number_comparison; 1399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label unordered; 1400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&generic_heap_number_comparison); 1401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FloatingPointHelper::CheckFloatOperands( 1402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm, &non_number_comparison, ebx); 1403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FloatingPointHelper::LoadFloatOperand(masm, eax); 1404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FloatingPointHelper::LoadFloatOperand(masm, edx); 1405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ FCmp(); 1406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Don't base result on EFLAGS when a NaN is involved. 1408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(parity_even, &unordered, Label::kNear); 1409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label below_label, above_label; 1411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Return a result of -1, 0, or 1, based on EFLAGS. 1412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(below, &below_label, Label::kNear); 1413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above, &above_label, Label::kNear); 1414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(0)); 1416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 1417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&below_label); 1419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Immediate(Smi::FromInt(-1))); 1420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 1421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&above_label); 1423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Immediate(Smi::FromInt(1))); 1424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 1425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If one of the numbers was NaN, then the result is always false. 1427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The cc is never not-equal. 1428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&unordered); 1429e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(cc != not_equal); 1430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (cc == less || cc == less_equal) { 1431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Immediate(Smi::FromInt(1))); 1432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 1433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Immediate(Smi::FromInt(-1))); 1434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 1436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The number comparison code did not provide a valid result. 1438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&non_number_comparison); 1439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Fast negative check for internalized-to-internalized equality. 1441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label check_for_strings; 1442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (cc == equal) { 1443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org BranchIfNotInternalizedString(masm, &check_for_strings, eax, ecx); 1444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org BranchIfNotInternalizedString(masm, &check_for_strings, edx, ecx); 1445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We've already checked for object identity, so if both operands 1447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // are internalized they aren't equal. Register eax already holds a 1448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // non-zero value, which indicates not equal, so just return. 1449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 1450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&check_for_strings); 1453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1454b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org __ JumpIfNotBothSequentialOneByteStrings(edx, eax, ecx, ebx, 1455b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org &check_unequal_objects); 1456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1457b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org // Inline comparison of one-byte strings. 1458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (cc == equal) { 1459b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org StringHelper::GenerateFlatOneByteStringEquals(masm, edx, eax, ecx, ebx); 1460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 1461b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, 1462b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org edi); 1463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG 1465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Abort(kUnexpectedFallThroughFromStringComparison); 1466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif 1467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&check_unequal_objects); 1469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (cc == equal && !strict()) { 1470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Non-strict equality. Objects are unequal if 1471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // they are both JSObjects and not undetectable, 1472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // and their pointers are different. 1473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label not_both_objects; 1474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label return_unequal; 1475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // At most one is a smi, so we can test for smi by adding the two. 1476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // A smi plus a heap object has the low bit set, a heap object plus 1477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // a heap object has the low bit clear. 1478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 1479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTagMask == 1); 1480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(ecx, Operand(eax, edx, times_1, 0)); 1481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, Immediate(kSmiTagMask)); 1482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, ¬_both_objects, Label::kNear); 1483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 1484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(below, ¬_both_objects, Label::kNear); 1485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(edx, FIRST_SPEC_OBJECT_TYPE, ebx); 1486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(below, ¬_both_objects, Label::kNear); 1487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We do not bail out after this point. Both are JSObjects, and 1488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // they are equal if and only if both are undetectable. 1489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The and of the undetectable flags is 1 if and only if they are equal. 1490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1 << Map::kIsUndetectable); 1492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &return_unequal, Label::kNear); 1493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), 1494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1 << Map::kIsUndetectable); 1495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &return_unequal, Label::kNear); 1496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The objects are both undetectable, so they both compare as the value 1497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // undefined, and are equal. 1498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(EQUAL)); 1499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&return_unequal); 1500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Return non-equal by returning the non-zero object pointer in eax, 1501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // or return equal if we fell through to here. 1502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); // rax, rdx were pushed 1503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_both_objects); 1504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Push arguments below the return address. 1507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ecx); 1508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); 1509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(eax); 1510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Figure out which native to call and setup the arguments. 1512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Builtins::JavaScript builtin; 1513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (cc == equal) { 1514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org builtin = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; 1515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 1516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org builtin = Builtins::COMPARE; 1517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); 1518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Restore return address on the stack. 1521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ecx); 1522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 1524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // tagged as a small integer. 1525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ InvokeBuiltin(builtin, JUMP_FUNCTION); 1526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 1528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateMiss(masm); 1529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void GenerateRecordCallTarget(MacroAssembler* masm) { 1533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Cache the called function in a feedback vector slot. Cache states 1534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // are uninitialized, monomorphic (indicated by a JSFunction), and 1535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // megamorphic. 1536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax : number of arguments to the construct function 1537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx : Feedback vector 1538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx : slot in feedback vector (Smi) 1539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi : the function to call 1540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Isolate* isolate = masm->isolate(); 1541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label initialize, done, miss, megamorphic, not_array_function; 1542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load the cache state into ecx. 1544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, 1545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArray::kHeaderSize)); 1546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // A monomorphic cache hit or an already megamorphic state: invoke the 1548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // function without changing the state. 1549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, edi); 1550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &done, Label::kFar); 1551a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); 1552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &done, Label::kFar); 1553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!FLAG_pretenuring_call_new) { 1555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If we came here, we need to see if we are the array function. 1556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If we didn't have a matching function, and we didn't find the megamorph 1557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // sentinel, then we have in the slot either some other function or an 1558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // AllocationSite. Do a map check on the object in ecx. 1559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Handle<Map> allocation_site_map = isolate->factory()->allocation_site_map(); 1560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map)); 1561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &miss); 1562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Make sure the function is the Array() function 1564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); 1565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edi, ecx); 1566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &megamorphic); 1567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&done, Label::kFar); 1568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 1571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // A monomorphic miss (i.e, here the cache is not uninitialized) goes 1573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // megamorphic. 1574a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ cmp(ecx, Immediate(TypeFeedbackVector::UninitializedSentinel(isolate))); 1575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &initialize); 1576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // MegamorphicSentinel is an immortal immovable object (undefined) so no 1577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // write-barrier is needed. 1578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&megamorphic); 1579a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ mov( 1580a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize), 1581a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); 1582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&done, Label::kFar); 1583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // An uninitialized cache is patched with the function or sentinel to 1585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // indicate the ElementsKind if function is the Array constructor. 1586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&initialize); 1587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!FLAG_pretenuring_call_new) { 1588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Make sure the function is the Array() function 1589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); 1590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edi, ecx); 1591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, ¬_array_function); 1592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The target function is the Array constructor, 1594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Create an AllocationSite if we don't already have it, store it in the 1595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // slot. 1596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org { 1597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 1598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Arguments register must be smi-tagged to call out. 1600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiTag(eax); 1601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(eax); 1602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edi); 1603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); 1604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ebx); 1605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CreateAllocationSiteStub create_stub(isolate); 1607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CallStub(&create_stub); 1608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ebx); 1610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edx); 1611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edi); 1612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(eax); 1613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(eax); 1614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&done); 1616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_array_function); 1618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(ebx, edx, times_half_pointer_size, 1621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArray::kHeaderSize), 1622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org edi); 1623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We won't need edx or ebx anymore, just save edi 1624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edi); 1625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ebx); 1626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); 162706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ RecordWriteArray(ebx, edi, edx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 162806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org OMIT_SMI_CHECK); 1629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edx); 1630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ebx); 1631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edi); 1632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 1634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { 1638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Do not transform the receiver for strict mode functions. 1639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 1640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), 1641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 1642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, cont); 1643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Do not transform the receiver for natives (shared already in ecx). 1645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), 1646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1 << SharedFunctionInfo::kNativeBitWithinByte); 1647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, cont); 1648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void EmitSlowCase(Isolate* isolate, 1652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MacroAssembler* masm, 1653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int argc, 1654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* non_function) { 1655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check for function proxy. 1656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); 1657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, non_function); 1658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ecx); 1659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edi); // put proxy as additional argument under return address 1660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ecx); 1661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(argc + 1)); 1662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(ebx, Immediate(0)); 1663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); 1664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org { 1665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); 1666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(adaptor, RelocInfo::CODE_TARGET); 1667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 1670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // of the original receiver from the call site). 1671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(non_function); 1672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, (argc + 1) * kPointerSize), edi); 1673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(argc)); 1674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(ebx, Immediate(0)); 1675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); 1676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); 1677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(adaptor, RelocInfo::CODE_TARGET); 1678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { 1682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Wrap the receiver and patch it back onto the stack. 1683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org { FrameScope frame_scope(masm, StackFrame::INTERNAL); 1684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edi); 1685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(eax); 1686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edi); 1688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, (argc + 1) * kPointerSize), eax); 1690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(cont); 1691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void CallFunctionNoFeedback(MacroAssembler* masm, 1695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int argc, bool needs_checks, 1696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org bool call_as_method) { 1697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi : the function to call 1698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label slow, non_function, wrap, cont; 1699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (needs_checks) { 1701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the function really is a JavaScript function. 1702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(edi, &non_function); 1703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Goto slow case if we do not have a function. 1705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 1706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &slow); 1707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Fast-case: Just invoke the function. 1710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ParameterCount actual(argc); 1711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (call_as_method) { 1713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (needs_checks) { 1714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org EmitContinueIfStrictOrNative(masm, &cont); 1715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load the receiver from the stack. 1718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, (argc + 1) * kPointerSize)); 1719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1720d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org if (needs_checks) { 1721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(eax, &wrap); 1722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 1724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(below, &wrap); 1725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 1726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&wrap); 1727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&cont); 1730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); 1733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (needs_checks) { 1735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Slow-case: Non-function called. 1736864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&slow); 1737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (non_function is bound in EmitSlowCase) 1738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org EmitSlowCase(masm->isolate(), masm, argc, &non_function); 1739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (call_as_method) { 1742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&wrap); 1743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org EmitWrapCase(masm, argc, &cont); 1744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid CallFunctionStub::Generate(MacroAssembler* masm) { 17497b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); 1750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid CallConstructStub::Generate(MacroAssembler* masm) { 1754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax : number of arguments 1755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx : feedback vector 1756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx : (only if ebx is not the megamorphic symbol) slot in feedback 1757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // vector (Smi) 1758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi : constructor function 1759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label slow, non_function_call; 1760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that function is not a smi. 1762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(edi, &non_function_call); 1763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that function is a JSFunction. 1764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 1765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &slow); 1766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (RecordCallTarget()) { 1768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateRecordCallTarget(masm); 1769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_pretenuring_call_new) { 1771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Put the AllocationSite from the feedback vector into ebx. 1772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // By adding kPointerSize we encode that we know the AllocationSite 1773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // entry is at the feedback vector slot given by edx + 1. 1774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size, 1775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArray::kHeaderSize + kPointerSize)); 1776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 1777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label feedback_register_initialized; 1778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Put the AllocationSite from the feedback vector into ebx, or undefined. 1779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size, 1780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArray::kHeaderSize)); 1781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Handle<Map> allocation_site_map = 1782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate()->factory()->allocation_site_map(); 1783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(FieldOperand(ebx, 0), Immediate(allocation_site_map)); 1784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &feedback_register_initialized); 1785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, isolate()->factory()->undefined_value()); 1786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&feedback_register_initialized); 1787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ AssertUndefinedOrAllocationSite(ebx); 1790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Jump to the function-specific construct stub. 1793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register jmp_reg = ecx; 1794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 1795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(jmp_reg, FieldOperand(jmp_reg, 1796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org SharedFunctionInfo::kConstructStubOffset)); 1797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize)); 1798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(jmp_reg); 1799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi: called object 1801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: number of arguments 1802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: object map 1803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label do_call; 1804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&slow); 1805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); 1806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &non_function_call); 1807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); 1808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&do_call); 1809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&non_function_call); 1811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 1812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&do_call); 1813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Set expected number of arguments to zero (not changing eax). 1814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(ebx, Immediate(0)); 1815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Handle<Code> arguments_adaptor = 1816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate()->builtins()->ArgumentsAdaptorTrampoline(); 1817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET); 1818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { 1822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset)); 1824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(vector, FieldOperand(vector, 1825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org SharedFunctionInfo::kFeedbackVectorOffset)); 1826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 18298d8413cae4e7eb777aaed22e2901c19f8d5d1297machenbach@chromium.orgvoid CallIC_ArrayStub::Generate(MacroAssembler* masm) { 1830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi - function 1831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx - slot id 18328d8413cae4e7eb777aaed22e2901c19f8d5d1297machenbach@chromium.org Label miss; 18337b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org int argc = arg_count(); 18348d8413cae4e7eb777aaed22e2901c19f8d5d1297machenbach@chromium.org ParameterCount actual(argc); 18358d8413cae4e7eb777aaed22e2901c19f8d5d1297machenbach@chromium.org 18368d8413cae4e7eb777aaed22e2901c19f8d5d1297machenbach@chromium.org EmitLoadTypeFeedbackVector(masm, ebx); 18378d8413cae4e7eb777aaed22e2901c19f8d5d1297machenbach@chromium.org 1838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); 1839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edi, ecx); 18408d8413cae4e7eb777aaed22e2901c19f8d5d1297machenbach@chromium.org __ j(not_equal, &miss); 1841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, arg_count()); 1843f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, 1844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArray::kHeaderSize)); 1845f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org 1846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Verify that ecx contains an AllocationSite 1847f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org Factory* factory = masm->isolate()->factory(); 1848f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 1849f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org factory->allocation_site_map()); 1850f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org __ j(not_equal, &miss); 1851f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org 1852f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org __ mov(ebx, ecx); 1853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ArrayConstructorStub stub(masm->isolate(), arg_count()); 1854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallStub(&stub); 1855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 1857a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org GenerateMiss(masm); 1858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The slow case, we need this no matter what to complete a call after a miss. 1860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CallFunctionNoFeedback(masm, 1861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org arg_count(), 1862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org true, 1863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CallAsMethod()); 1864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Unreachable. 1866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ int3(); 1867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid CallICStub::Generate(MacroAssembler* masm) { 1871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi - function 1872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx - slot id 1873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Isolate* isolate = masm->isolate(); 1874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label extra_checks_or_miss, slow_start; 1875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label slow, non_function, wrap, cont; 1876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label have_js_function; 18777b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org int argc = arg_count(); 1878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ParameterCount actual(argc); 1879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org EmitLoadTypeFeedbackVector(masm, ebx); 1881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The checks. First, does edi match the recorded monomorphic target? 1883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edi, FieldOperand(ebx, edx, times_half_pointer_size, 1884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArray::kHeaderSize)); 1885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &extra_checks_or_miss); 1886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&have_js_function); 18887b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org if (CallAsMethod()) { 1889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org EmitContinueIfStrictOrNative(masm, &cont); 1890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load the receiver from the stack. 1892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, (argc + 1) * kPointerSize)); 1893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(eax, &wrap); 1895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 1897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(below, &wrap); 1898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&cont); 1900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); 1903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&slow); 1905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org EmitSlowCase(isolate, masm, argc, &non_function); 1906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 19077b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org if (CallAsMethod()) { 1908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&wrap); 1909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org EmitWrapCase(masm, argc, &cont); 1910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&extra_checks_or_miss); 1913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label miss; 1914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, 1916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArray::kHeaderSize)); 1917a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); 1918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &slow_start); 1919a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org __ cmp(ecx, Immediate(TypeFeedbackVector::UninitializedSentinel(isolate))); 1920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &miss); 1921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!FLAG_trace_ic) { 1923f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org // We are going megamorphic. If the feedback is a JSFunction, it is fine 1924f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org // to handle it here. More complex cases are dealt with in the runtime. 1925f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org __ AssertNotSmi(ecx); 1926f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx); 1927f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org __ j(not_equal, &miss); 1928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(ebx, edx, times_half_pointer_size, 1929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArray::kHeaderSize), 1930a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); 1931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&slow_start); 1932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We are here because tracing is on or we are going monomorphic. 1935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 1936a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org GenerateMiss(masm); 1937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // the slow case 1939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&slow_start); 1940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the function really is a JavaScript function. 1942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(edi, &non_function); 1943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Goto slow case if we do not have a function. 1945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 1946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &slow); 1947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&have_js_function); 1948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Unreachable 1950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ int3(); 1951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1954a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgvoid CallICStub::GenerateMiss(MacroAssembler* masm) { 1955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get the receiver of the function from the stack; 1 ~ return address. 19567b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org __ mov(ecx, Operand(esp, (arg_count() + 1) * kPointerSize)); 1957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org { 1959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 1960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Push the receiver and the function and feedback info. 1962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ecx); 1963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edi); 1964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ebx); 1965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); 1966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Call the entry. 1968a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss 1969a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org : IC::kCallIC_Customization_Miss; 1970a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 19718d8413cae4e7eb777aaed22e2901c19f8d5d1297machenbach@chromium.org ExternalReference miss = ExternalReference(IC_Utility(id), 1972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->isolate()); 1973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CallExternalReference(miss, 4); 1974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Move result to edi and exit the internal frame. 1976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, eax); 1977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 1978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgbool CEntryStub::NeedsImmovableCode() { 1982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org return false; 1983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 1987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CEntryStub::GenerateAheadOfTime(isolate); 1988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 1989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 1990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // It is important that the store buffer overflow stubs are generated first. 1991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 1992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 1993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org BinaryOpICStub::GenerateAheadOfTime(isolate); 1994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 1995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 1996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid CodeStub::GenerateFPStubs(Isolate* isolate) { 199906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org CEntryStub save_doubles(isolate, 1, kSaveFPRegs); 200006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org // Stubs might already be in the snapshot, detect that and don't regenerate, 200106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org // which would lead to code stub initialization state being messed up. 200206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org Code* save_doubles_code; 200306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org if (!save_doubles.FindCodeInCache(&save_doubles_code)) { 200406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org save_doubles_code = *(save_doubles.GetCode()); 200506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org } 200606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org isolate->set_fp_stubs_generated(true); 2007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 201106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org CEntryStub stub(isolate, 1, kDontSaveFPRegs); 2012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stub.GetCode(); 2013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid CEntryStub::Generate(MacroAssembler* masm) { 2017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: number of arguments including receiver 2018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: pointer to C function (C callee-saved) 2019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebp: frame pointer (restored after C call) 2020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp: stack pointer (restored after C call) 2021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esi: current context (C callee-saved) 2022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi: JS function of the caller (C callee-saved) 2023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ProfileEntryHookStub::MaybeCallEntryHook(masm); 2025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Enter the exit frame that transitions from JavaScript to C++. 202706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ EnterExitFrame(save_doubles()); 2028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: pointer to C function (C callee-saved) 2030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebp: frame pointer (restored after C call) 2031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp: stack pointer (restored after C call) 2032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi: number of arguments including receiver (C callee-saved) 2033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esi: pointer to the first argument (C callee-saved) 2034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 20356474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Result returned in eax, or eax+edx if result size is 2. 2036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check stack alignment. 2038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 2039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CheckStackAlignment(); 2040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Call C function. 2043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 0 * kPointerSize), edi); // argc. 2044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 1 * kPointerSize), esi); // argv. 2045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 2 * kPointerSize), 2046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(ExternalReference::isolate_address(isolate()))); 2047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ call(ebx); 2048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Result is in eax or edx:eax - do not destroy these registers! 2049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Runtime functions should not return 'the hole'. Allowing it to escape may 2051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // lead to crashes in the IC code later. 2052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 2053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label okay; 2054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, isolate()->factory()->the_hole_value()); 2055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &okay, Label::kNear); 2056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ int3(); 2057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&okay); 2058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check result for exception sentinel. 2061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label exception_returned; 2062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, isolate()->factory()->exception()); 2063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &exception_returned); 2064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference pending_exception_address( 2066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Isolate::kPendingExceptionAddress, isolate()); 2067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that there is no pending exception, otherwise we 2069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // should have returned the exception sentinel. 2070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 2071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); 2072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Immediate(isolate()->factory()->the_hole_value())); 2073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label okay; 2074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edx, Operand::StaticVariable(pending_exception_address)); 2075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Cannot use check here as it attempts to generate call into runtime. 2076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &okay, Label::kNear); 2077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ int3(); 2078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&okay); 2079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edx); 2080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Exit the JavaScript to C++ exit frame. 208306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ LeaveExitFrame(save_doubles()); 2084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 2085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Handling of exception. 2087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&exception_returned); 2088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Retrieve the pending exception. 2090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand::StaticVariable(pending_exception_address)); 2091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Clear the pending exception. 2093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Immediate(isolate()->factory()->the_hole_value())); 2094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand::StaticVariable(pending_exception_address), edx); 2095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Special handling of termination exceptions which are uncatchable 2097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // by javascript code. 2098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label throw_termination_exception; 2099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, isolate()->factory()->termination_exception()); 2100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &throw_termination_exception); 2101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Handle normal exception. 2103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Throw(eax); 2104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&throw_termination_exception); 2106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ThrowUncatchable(eax); 2107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 21102c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid JSEntryStub::Generate(MacroAssembler* masm) { 2111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label invoke, handler_entry, exit; 2112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label not_outermost_js, not_outermost_js_2; 2113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ProfileEntryHookStub::MaybeCallEntryHook(masm); 2115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Set up frame. 2117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ebp); 2118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebp, esp); 2119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Push marker in two places. 21212c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org int marker = type(); 2122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Immediate(Smi::FromInt(marker))); // context slot 2123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Immediate(Smi::FromInt(marker))); // function slot 2124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Save callee-saved registers (C calling conventions). 2125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edi); 2126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(esi); 2127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ebx); 2128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Save copies of the top frame descriptor on the stack. 2130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference c_entry_fp(Isolate::kCEntryFPAddress, isolate()); 2131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Operand::StaticVariable(c_entry_fp)); 2132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If this is the outermost JS call, set js_entry_sp value. 2134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate()); 2135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0)); 2136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, ¬_outermost_js, Label::kNear); 2137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand::StaticVariable(js_entry_sp), ebp); 2138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); 2139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&invoke, Label::kNear); 2140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_outermost_js); 2141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Immediate(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME))); 2142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Jump to a faked try block that does the invoke, with a faked catch 2144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // block that sets the pending exception. 2145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&invoke); 2146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&handler_entry); 2147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org handler_offset_ = handler_entry.pos(); 2148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Caught exception: Store result (exception) in the pending exception 2149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // field in the JSEnv and return a failure sentinel. 2150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference pending_exception(Isolate::kPendingExceptionAddress, 2151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate()); 2152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand::StaticVariable(pending_exception), eax); 2153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Immediate(isolate()->factory()->exception())); 2154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&exit); 2155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Invoke: Link this frame into the handler chain. There's only one 2157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // handler block in this code object, so its index is 0. 2158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&invoke); 2159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ PushTryHandler(StackHandler::JS_ENTRY, 0); 2160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Clear any pending exceptions. 2162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Immediate(isolate()->factory()->the_hole_value())); 2163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand::StaticVariable(pending_exception), edx); 2164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Fake a receiver (NULL). 2166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Immediate(0)); // receiver 2167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Invoke the function by calling through JS entry trampoline builtin and 2169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // pop the faked function when we return. Notice that we cannot store a 2170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // reference to the trampoline code directly in this stub, because the 2171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // builtin stubs may not have been generated yet. 21722c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if (type() == StackFrame::ENTRY_CONSTRUCT) { 2173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline, 2174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate()); 2175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Immediate(construct_entry)); 2176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 2177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference entry(Builtins::kJSEntryTrampoline, isolate()); 2178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Immediate(entry)); 2179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Operand(edx, 0)); // deref address 2181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); 2182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ call(edx); 2183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Unlink this frame from the handler chain. 2185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ PopTryHandler(); 2186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&exit); 2188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check if the current stack frame is marked as the outermost JS frame. 2189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ebx); 2190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ebx, Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); 2191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, ¬_outermost_js_2); 2192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand::StaticVariable(js_entry_sp), Immediate(0)); 2193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_outermost_js_2); 2194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Restore the top frame descriptor from the stack. 2196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(Operand::StaticVariable(ExternalReference( 2197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Isolate::kCEntryFPAddress, isolate()))); 2198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Restore callee-saved registers (C calling conventions). 2200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ebx); 2201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(esi); 2202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edi); 2203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(esp, Immediate(2 * kPointerSize)); // remove markers 2204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Restore frame pointer and return. 2206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ebp); 2207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 2208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Generate stub code for instanceof. 2212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// This code can patch a call site inlined cache of the instance of check, 2213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// which looks like this. 2214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// 2215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// 81 ff XX XX XX XX cmp edi, <the hole, patched to a map> 2216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// 75 0a jne <some near label> 2217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// b8 XX XX XX XX mov eax, <the hole, patched to either true or false> 2218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// 2219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// If call site patching is requested the stack will have the delta from the 2220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// return address to the cmp instruction just below the return address. This 2221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// also means that call site patching can only take place with arguments in 2222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// registers. TOS looks like this when call site patching is requested 2223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// 2224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// esp[0] : return address 2225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// esp[4] : delta from return address to cmp instruction 2226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// 2227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid InstanceofStub::Generate(MacroAssembler* masm) { 2228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Call site inlining and patching implies arguments in registers. 2229e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(HasArgsInRegisters() || !HasCallSiteInlineCheck()); 2230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Fixed register usage throughout the stub. 2232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register object = eax; // Object (lhs). 2233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register map = ebx; // Map of the object. 2234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register function = edx; // Function (rhs). 2235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register prototype = edi; // Prototype of the function. 2236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch = ecx; 2237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Constants describing the call site code to patch. 2239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kDeltaToCmpImmediate = 2; 2240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kDeltaToMov = 8; 2241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org static const int kDeltaToMovImmediate = 9; 2242e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org static const int8_t kCmpEdiOperandByte1 = bit_cast<int8_t, uint8_t>(0x3b); 2243e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org static const int8_t kCmpEdiOperandByte2 = bit_cast<int8_t, uint8_t>(0x3d); 2244e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org static const int8_t kMovEaxImmediateByte = bit_cast<int8_t, uint8_t>(0xb8); 2245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2246e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(object.code(), InstanceofStub::left().code()); 2247e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(function.code(), InstanceofStub::right().code()); 2248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get the object and function - they are always both needed. 2250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label slow, not_js_object; 2251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!HasArgsInRegisters()) { 2252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(object, Operand(esp, 2 * kPointerSize)); 2253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(function, Operand(esp, 1 * kPointerSize)); 2254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the left hand is a JS object. 2257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(object, ¬_js_object); 2258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); 2259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If there is a call site cache don't look in the global cache, but do the 2261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // real lookup and update the call site cache. 22625c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) { 2263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Look up the function and the map in the instanceof cache. 2264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label miss; 2265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); 2266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &miss, Label::kNear); 2267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CompareRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex); 2268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &miss, Label::kNear); 2269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex); 2270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 2271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 2272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get the prototype of the function. 2275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); 2276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that the function prototype is a JS object. 2278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(prototype, &slow); 2279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); 2280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Update the global instanceof or call site inlined cache with the current 2282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // map and function. The cached answer will be set when it is known below. 2283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!HasCallSiteInlineCheck()) { 2284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ StoreRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex); 2285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ StoreRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); 2286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 2287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The constants for the code patching are based on no push instructions 2288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // at the call site. 2289e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(HasArgsInRegisters()); 2290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get return address and delta to inlined map check. 2291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, Operand(esp, 0 * kPointerSize)); 2292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(scratch, Operand(esp, 1 * kPointerSize)); 2293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 2294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1); 2295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp1); 2296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmpb(Operand(scratch, 1), kCmpEdiOperandByte2); 2297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp2); 2298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, Operand(scratch, kDeltaToCmpImmediate)); 2300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(scratch, 0), map); 2301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Loop through the prototype chain of the object looking for the function 2304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // prototype. 2305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset)); 2306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label loop, is_instance, is_not_instance; 2307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&loop); 2308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(scratch, prototype); 2309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &is_instance, Label::kNear); 2310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Factory* factory = isolate()->factory(); 2311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(scratch, Immediate(factory->null_value())); 2312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &is_not_instance, Label::kNear); 2313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 2314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); 2315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&loop); 2316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&is_instance); 2318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!HasCallSiteInlineCheck()) { 2319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Immediate(0)); 2320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); 23215c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org if (ReturnTrueFalseObject()) { 23225c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org __ mov(eax, factory->true_value()); 23235c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org } 2324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 2325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get return address and delta to inlined map check. 2326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, factory->true_value()); 2327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, Operand(esp, 0 * kPointerSize)); 2328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(scratch, Operand(esp, 1 * kPointerSize)); 2329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 2330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); 2331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); 2332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(scratch, kDeltaToMovImmediate), eax); 2334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!ReturnTrueFalseObject()) { 2335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(0)); 2336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 2339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&is_not_instance); 2341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!HasCallSiteInlineCheck()) { 2342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Immediate(Smi::FromInt(1))); 2343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); 23445c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org if (ReturnTrueFalseObject()) { 23455c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org __ mov(eax, factory->false_value()); 23465c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org } 2347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 2348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get return address and delta to inlined map check. 2349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, factory->false_value()); 2350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, Operand(esp, 0 * kPointerSize)); 2351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(scratch, Operand(esp, 1 * kPointerSize)); 2352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 2353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); 2354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); 2355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(scratch, kDeltaToMovImmediate), eax); 2357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!ReturnTrueFalseObject()) { 2358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(1))); 2359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 2362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label object_not_null, object_not_null_or_smi; 2364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_js_object); 2365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Before null, smi and string value checks, check that the rhs is a function 2366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // as for a non-function rhs an exception needs to be thrown. 2367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(function, &slow, Label::kNear); 2368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); 2369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &slow, Label::kNear); 2370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Null is not instance of anything. 2372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(object, factory->null_value()); 2373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &object_not_null, Label::kNear); 23745c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org if (ReturnTrueFalseObject()) { 23755c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org __ mov(eax, factory->false_value()); 23765c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org } else { 23775c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(1))); 23785c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org } 2379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 2380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&object_not_null); 2382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Smi values is not instance of anything. 2383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(object, &object_not_null_or_smi, Label::kNear); 23845c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org if (ReturnTrueFalseObject()) { 23855c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org __ mov(eax, factory->false_value()); 23865c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org } else { 23875c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(1))); 23885c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org } 2389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 2390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&object_not_null_or_smi); 2392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // String values is not instance of anything. 2393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Condition is_string = masm->IsObjectStringType(object, scratch, scratch); 2394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(NegateCondition(is_string), &slow, Label::kNear); 23955c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org if (ReturnTrueFalseObject()) { 23965c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org __ mov(eax, factory->false_value()); 23975c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org } else { 23985c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(1))); 23995c0fd9bca25be110d9fb3e332075726b10c8b169machenbach@chromium.org } 2400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 2401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Slow-case: Go through the JavaScript implementation. 2403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&slow); 2404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!ReturnTrueFalseObject()) { 2405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Tail call the builtin which returns 0 or 1. 2406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (HasArgsInRegisters()) { 2407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Push arguments below return address. 2408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(scratch); 2409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(object); 2410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(function); 2411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(scratch); 2412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 2414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 2415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Call the builtin and convert 0/1 to true/false. 2416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org { 2417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 2418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(object); 2419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(function); 2420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); 2421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label true_value, done; 2423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(eax, eax); 2424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &true_value, Label::kNear); 2425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, factory->false_value()); 2426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&done, Label::kNear); 2427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&true_value); 2428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, factory->true_value()); 2429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 2430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 2431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// ------------------------------------------------------------------------- 2436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// StringCharCodeAtGenerator 2437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 2439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If the receiver is a smi trigger the non-string case. 2440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 2441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(object_, receiver_not_string_); 2442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Fetch the instance type of the receiver into result register. 2444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); 2445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 2446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If the receiver is not a string trigger the non-string case. 2447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(result_, Immediate(kIsNotStringMask)); 2448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, receiver_not_string_); 2449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If the index is non-smi trigger the non-smi case. 2451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 2452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(index_, &index_not_smi_); 2453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&got_smi_index_); 2454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check for index out of range. 2456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(index_, FieldOperand(object_, String::kLengthOffset)); 2457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above_equal, index_out_of_range_); 2458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(index_); 2460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Factory* factory = masm->isolate()->factory(); 2462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org StringCharLoadGenerator::Generate( 2463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm, factory, object_, index_, result_, &call_runtime_); 2464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiTag(result_); 2466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&exit_); 2467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid StringCharCodeAtGenerator::GenerateSlow( 2471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MacroAssembler* masm, 2472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org const RuntimeCallHelper& call_helper) { 2473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase); 2474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Index is not a smi. 2476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&index_not_smi_); 2477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If index is a heap number, try converting it to an integer. 2478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CheckMap(index_, 2479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->isolate()->factory()->heap_number_map(), 2480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org index_not_number_, 2481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org DONT_DO_SMI_CHECK); 2482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org call_helper.BeforeCall(masm); 2483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(object_); 2484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(index_); // Consumed by runtime conversion function. 2485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (index_flags_ == STRING_INDEX_IS_NUMBER) { 2486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); 2487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 2488e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 2489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // NumberToSmi discards numbers that are not exact integers. 249047390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org __ CallRuntime(Runtime::kNumberToSmi, 1); 2491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!index_.is(eax)) { 2493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Save the conversion result before the pop instructions below 2494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // have a chance to overwrite it. 2495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(index_, eax); 2496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(object_); 2498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Reload the instance type. 2499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); 2500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 2501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org call_helper.AfterCall(masm); 2502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If index is still not a smi, it must be out of range. 2503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 2504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(index_, index_out_of_range_); 2505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Otherwise, return to the fast path. 2506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&got_smi_index_); 2507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Call runtime. We get here when the receiver is a string and the 2509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // index is a number, but the code of getting the actual character 2510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // is too complex (e.g., when the string needs to be flattened). 2511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&call_runtime_); 2512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org call_helper.BeforeCall(masm); 2513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(object_); 2514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiTag(index_); 2515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(index_); 251647390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org __ CallRuntime(Runtime::kStringCharCodeAtRT, 2); 2517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!result_.is(eax)) { 2518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(result_, eax); 2519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org call_helper.AfterCall(masm); 2521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&exit_); 2522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); 2524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// ------------------------------------------------------------------------- 2528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// StringCharFromCodeGenerator 2529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 2531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Fast case of Heap::LookupSingleCharacterStringFromCode. 2532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 2533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiShiftSize == 0); 25349aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCode + 1)); 2535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(code_, 2536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(kSmiTagMask | 2537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ((~String::kMaxOneByteCharCode) << kSmiTagSize))); 2538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &slow_case_); 2539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Factory* factory = masm->isolate()->factory(); 2541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(result_, Immediate(factory->single_character_string_cache())); 2542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 2543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTagSize == 1); 2544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiShiftSize == 0); 2545b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org // At this point code register contains smi tagged one byte char code. 2546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(result_, FieldOperand(result_, 2547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org code_, times_half_pointer_size, 2548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArray::kHeaderSize)); 2549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(result_, factory->undefined_value()); 2550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &slow_case_); 2551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&exit_); 2552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid StringCharFromCodeGenerator::GenerateSlow( 2556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MacroAssembler* masm, 2557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org const RuntimeCallHelper& call_helper) { 2558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); 2559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&slow_case_); 2561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org call_helper.BeforeCall(masm); 2562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(code_); 2563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CallRuntime(Runtime::kCharFromCode, 1); 2564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!result_.is(eax)) { 2565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(result_, eax); 2566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org call_helper.AfterCall(masm); 2568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&exit_); 2569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 2571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 25748ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.orgvoid StringHelper::GenerateCopyCharacters(MacroAssembler* masm, 25758ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org Register dest, 25768ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org Register src, 25778ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org Register count, 25788ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org Register scratch, 25798ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org String::Encoding encoding) { 2580e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!scratch.is(dest)); 2581e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!scratch.is(src)); 2582e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!scratch.is(count)); 2583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Nothing to do for zero characters. 2585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label done; 2586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(count, count); 2587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &done); 2588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Make count the number of bytes to copy. 25908ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org if (encoding == String::TWO_BYTE_ENCODING) { 2591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ shl(count, 1); 2592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label loop; 2595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&loop); 2596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov_b(scratch, Operand(src, 0)); 2597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov_b(Operand(dest, 0), scratch); 25988ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org __ inc(src); 25998ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org __ inc(dest); 26008ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org __ dec(count); 2601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &loop); 2602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 2604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid SubStringStub::Generate(MacroAssembler* masm) { 2608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label runtime; 2609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Stack frame on entry. 2611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0]: return address 2612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[4]: to 2613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[8]: from 2614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[12]: string 2615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Make sure first argument is a string. 2617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, 3 * kPointerSize)); 2618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 2619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(eax, &runtime); 2620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); 2621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(NegateCondition(is_string), &runtime); 2622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: string 2624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: instance type 2625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Calculate length of sub string using the smi values. 2627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(esp, 1 * kPointerSize)); // To index. 2628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(ecx, &runtime); 2629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Operand(esp, 2 * kPointerSize)); // From index. 2630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(edx, &runtime); 2631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(ecx, edx); 2632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, FieldOperand(eax, String::kLengthOffset)); 2633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label not_original_string; 2634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Shorter than original string's length: an actual substring. 2635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(below, ¬_original_string, Label::kNear); 2636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Longer than original string's length or negative: unsafe arguments. 2637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above, &runtime); 2638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Return original string. 2639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Counters* counters = isolate()->counters(); 2640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ IncrementCounter(counters->sub_string_native(), 1); 2641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(3 * kPointerSize); 2642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_original_string); 2643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label single_char; 2645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, Immediate(Smi::FromInt(1))); 2646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &single_char); 2647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: string 2649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: instance type 2650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: sub string length (smi) 2651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: from index (smi) 2652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Deal with different string types: update the index if necessary 2653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // and put the underlying string into edi. 2654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label underlying_unpacked, sliced_string, seq_or_external_string; 2655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If the string is not indirect, it can only be sequential or external. 2656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); 2657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kIsIndirectStringMask != 0); 2658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ebx, Immediate(kIsIndirectStringMask)); 2659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &seq_or_external_string, Label::kNear); 2660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Factory* factory = isolate()->factory(); 2662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ebx, Immediate(kSlicedNotConsMask)); 2663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &sliced_string, Label::kNear); 2664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Cons string. Check whether it is flat, then fetch first part. 2665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Flat cons strings have an empty second part. 2666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(FieldOperand(eax, ConsString::kSecondOffset), 2667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org factory->empty_string()); 2668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &runtime); 2669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, FieldOperand(eax, ConsString::kFirstOffset)); 2670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Update instance type. 2671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset)); 2672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 2673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&underlying_unpacked, Label::kNear); 2674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&sliced_string); 2676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Sliced string. Fetch parent and adjust start index by offset. 2677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(edx, FieldOperand(eax, SlicedString::kOffsetOffset)); 2678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, FieldOperand(eax, SlicedString::kParentOffset)); 2679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Update instance type. 2680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset)); 2681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 2682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&underlying_unpacked, Label::kNear); 2683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&seq_or_external_string); 2685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Sequential or external string. Just move string to the expected register. 2686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, eax); 2687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&underlying_unpacked); 2689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_string_slices) { 2691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label copy_routine; 2692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi: underlying subject string 2693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: instance type of underlying subject string 2694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: adjusted start index (smi) 2695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: length (smi) 2696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, Immediate(Smi::FromInt(SlicedString::kMinLength))); 2697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Short slice. Copy instead of slicing. 2698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(less, ©_routine); 2699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Allocate new sliced string. At this point we do not reload the instance 2700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // type including the string encoding because we simply rely on the info 2701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // provided by the original string. It does not matter if the original 2702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // string's encoding is wrong because we always have to recheck encoding of 2703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // the newly created string's parent anyways due to externalized strings. 2704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label two_byte_slice, set_slice_header; 2705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); 2706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 2707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ebx, Immediate(kStringEncodingMask)); 2708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &two_byte_slice, Label::kNear); 2709b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org __ AllocateOneByteSlicedString(eax, ebx, no_reg, &runtime); 2710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&set_slice_header, Label::kNear); 2711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&two_byte_slice); 2712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ AllocateTwoByteSlicedString(eax, ebx, no_reg, &runtime); 2713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&set_slice_header); 2714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx); 2715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset), 2716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(String::kEmptyHashField)); 2717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi); 2718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx); 2719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ IncrementCounter(counters->sub_string_native(), 1); 2720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(3 * kPointerSize); 2721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(©_routine); 2723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 2724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi: underlying subject string 2726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: instance type of underlying subject string 2727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: adjusted start index (smi) 2728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: length (smi) 2729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The subject string can only be external or sequential string of either 2730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // encoding at this point. 2731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label two_byte_sequential, runtime_drop_two, sequential_string; 2732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kExternalStringTag != 0); 2733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSeqStringTag == 0); 2734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(ebx, kExternalStringTag); 2735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &sequential_string); 2736864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Handle external string. 2738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Rule out short external strings. 2739d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org STATIC_ASSERT(kShortExternalStringTag != 0); 2740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(ebx, kShortExternalStringMask); 2741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &runtime); 2742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset)); 2743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Move the pointer so that offset-wise, it looks like a sequential string. 2744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 2745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(edi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 2746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&sequential_string); 2748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Stash away (adjusted) index and (underlying) string. 2749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); 2750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edi); 2751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(ecx); 2752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); 2753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(ebx, kStringEncodingMask); 2754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &two_byte_sequential); 2755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2756b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org // Sequential one byte string. Allocate the result. 2757b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org __ AllocateOneByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two); 2758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: result string 2760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: result string length 2761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Locate first character of result. 2762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, eax); 2763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 2764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load string argument and locate character of sub string start. 27658ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org __ pop(edx); 2766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ebx); 2767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(ebx); 27688ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org __ lea(edx, FieldOperand(edx, ebx, times_1, SeqOneByteString::kHeaderSize)); 2769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: result string 2771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: result length 2772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi: first character of result 27738ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org // edx: character of sub string start 27748ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org StringHelper::GenerateCopyCharacters( 27758ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org masm, edi, edx, ecx, ebx, String::ONE_BYTE_ENCODING); 2776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ IncrementCounter(counters->sub_string_native(), 1); 2777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(3 * kPointerSize); 2778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&two_byte_sequential); 2780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Sequential two-byte string. Allocate the result. 2781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ AllocateTwoByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two); 2782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: result string 2784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: result string length 2785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Locate first character of result. 2786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, eax); 2787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(edi, 2788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 2789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load string argument and locate character of sub string start. 27908ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org __ pop(edx); 2791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ebx); 2792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // As from is a smi it is 2 times the value which matches the size of a two 2793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // byte character. 2794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 2795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 27968ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org __ lea(edx, FieldOperand(edx, ebx, times_1, SeqTwoByteString::kHeaderSize)); 2797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: result string 2799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: result length 2800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi: first character of result 28018ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org // edx: character of sub string start 28028ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org StringHelper::GenerateCopyCharacters( 28038ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org masm, edi, edx, ecx, ebx, String::TWO_BYTE_ENCODING); 2804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ IncrementCounter(counters->sub_string_native(), 1); 2805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(3 * kPointerSize); 2806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Drop pushed values on the stack before tail call. 2808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&runtime_drop_two); 2809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Drop(2); 2810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Just jump to runtime to create the sub string. 2812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&runtime); 281347390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org __ TailCallRuntime(Runtime::kSubString, 3, 1); 2814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&single_char); 2816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax: string 2817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx: instance type 2818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ecx: sub string length (smi) 2819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx: from index (smi) 2820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org StringCharAtGenerator generator( 2821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org eax, edx, ecx, eax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); 2822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org generator.GenerateFast(masm); 2823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(3 * kPointerSize); 2824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org generator.SkipSlow(masm, &runtime); 2825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2828b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, 2829b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Register left, 2830b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Register right, 2831b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Register scratch1, 2832b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org Register scratch2) { 2833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register length = scratch1; 2834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compare lengths. 2836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label strings_not_equal, check_zero_length; 2837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(length, FieldOperand(left, String::kLengthOffset)); 2838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(length, FieldOperand(right, String::kLengthOffset)); 2839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &check_zero_length, Label::kNear); 2840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&strings_not_equal); 2841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(NOT_EQUAL))); 2842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 2843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check if the length is zero. 2845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label compare_chars; 2846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&check_zero_length); 2847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 2848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(length, length); 2849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &compare_chars, Label::kNear); 2850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(EQUAL))); 2851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 2852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compare characters. 2854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&compare_chars); 2855b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, 2856b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org &strings_not_equal, Label::kNear); 2857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Characters are equal. 2859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(EQUAL))); 2860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 2861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2864b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid StringHelper::GenerateCompareFlatOneByteStrings( 28659aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org MacroAssembler* masm, Register left, Register right, Register scratch1, 28669aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org Register scratch2, Register scratch3) { 2867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Counters* counters = masm->isolate()->counters(); 2868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ IncrementCounter(counters->string_compare_native(), 1); 2869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Find minimum length. 2871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label left_shorter; 2872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); 2873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch3, scratch1); 2874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); 2875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register length_delta = scratch3; 2877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(less_equal, &left_shorter, Label::kNear); 2879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Right string is shorter. Change scratch1 to be length of right string. 2880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(scratch1, length_delta); 2881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&left_shorter); 2882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register min_length = scratch1; 2884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If either length is zero, just compare lengths. 2886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label compare_lengths; 2887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(min_length, min_length); 2888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &compare_lengths, Label::kNear); 2889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compare characters. 2891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label result_not_equal; 2892b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2, 2893b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org &result_not_equal, Label::kNear); 2894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compare lengths - strings up to min-length are equal. 2896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&compare_lengths); 2897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(length_delta, length_delta); 2898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label length_not_equal; 2899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &length_not_equal, Label::kNear); 2900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Result is EQUAL. 2902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(EQUAL == 0); 2903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 2904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(EQUAL))); 2905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 2906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label result_greater; 2908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label result_less; 2909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&length_not_equal); 2910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(greater, &result_greater, Label::kNear); 2911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&result_less, Label::kNear); 2912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&result_not_equal); 2913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(above, &result_greater, Label::kNear); 2914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&result_less); 2915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Result is LESS. 2917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(LESS))); 2918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 2919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Result is GREATER. 2921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&result_greater); 2922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(GREATER))); 2923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 2924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2927b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid StringHelper::GenerateOneByteCharsCompareLoop( 29289aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org MacroAssembler* masm, Register left, Register right, Register length, 29299aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org Register scratch, Label* chars_not_equal, 2930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label::Distance chars_not_equal_near) { 2931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Change index to run from -length to -1 by adding length to string 2932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // start. This means that loop ends when index reaches zero, which 2933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // doesn't need an additional compare. 2934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(length); 2935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(left, 2936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize)); 2937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(right, 2938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FieldOperand(right, length, times_1, SeqOneByteString::kHeaderSize)); 2939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ neg(length); 2940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register index = length; // index = -length; 2941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compare loop. 2943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label loop; 2944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&loop); 2945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov_b(scratch, Operand(left, index, times_1, 0)); 2946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmpb(scratch, Operand(right, index, times_1, 0)); 2947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, chars_not_equal, chars_not_equal_near); 2948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ inc(index); 2949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &loop); 2950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid StringCompareStub::Generate(MacroAssembler* masm) { 2954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label runtime; 2955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Stack frame on entry. 2957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0]: return address 2958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[4]: right string 2959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[8]: left string 2960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Operand(esp, 2 * kPointerSize)); // left 2962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, 1 * kPointerSize)); // right 2963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label not_same; 2965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edx, eax); 2966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, ¬_same, Label::kNear); 2967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(EQUAL == 0); 2968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 2969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(EQUAL))); 2970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ IncrementCounter(isolate()->counters()->string_compare_native(), 1); 2971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(2 * kPointerSize); 2972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_same); 2974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2975b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org // Check that both objects are sequential one-byte strings. 2976b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org __ JumpIfNotBothSequentialOneByteStrings(edx, eax, ecx, ebx, &runtime); 2977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2978b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org // Compare flat one-byte strings. 2979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Drop arguments from the stack. 2980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ecx); 2981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(esp, Immediate(2 * kPointerSize)); 2982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ecx); 2983b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, 2984b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org edi); 2985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 2987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // tagged as a small integer. 2988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&runtime); 298947390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 2990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 2991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 2993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { 2994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------- S t a t e ------------- 2995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- edx : left 2996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- eax : right 2997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[0] : return address 2998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------------------------------- 2999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load ecx with the allocation site. We stick an undefined dummy value here 3001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // and replace it with the real allocation site later when we instantiate this 3002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate(). 3003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, handle(isolate()->heap()->undefined_value())); 3004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Make sure that we actually patched the allocation site. 3006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 3007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, Immediate(kSmiTagMask)); 3008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(not_equal, kExpectedAllocationSite); 3009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 3010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate()->factory()->allocation_site_map()); 3011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(equal, kExpectedAllocationSite); 3012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Tail call into the stub that handles binary operations with allocation 3015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // sites. 30165fc1eed70f85bd1e9d0833742945798d6ef49cf0machenbach@chromium.org BinaryOpWithAllocationSiteStub stub(isolate(), state()); 3017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallStub(&stub); 3018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 302142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.orgvoid CompareICStub::GenerateSmis(MacroAssembler* masm) { 3022a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org DCHECK(state() == CompareICState::SMI); 3023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label miss; 3024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, edx); 3025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ or_(ecx, eax); 3026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(ecx, &miss, Label::kNear); 3027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (GetCondition() == equal) { 3029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // For equality we do not care about the sign of the result. 3030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(eax, edx); 3031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 3032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label done; 3033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(edx, eax); 3034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(no_overflow, &done, Label::kNear); 3035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Correct sign of result in case of overflow. 3036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ not_(edx); 3037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 3038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, edx); 3039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 3043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateMiss(masm); 3044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 304742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.orgvoid CompareICStub::GenerateNumbers(MacroAssembler* masm) { 3048a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org DCHECK(state() == CompareICState::NUMBER); 3049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label generic_stub; 3051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label unordered, maybe_undefined1, maybe_undefined2; 3052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label miss; 3053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3054a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org if (left() == CompareICState::SMI) { 3055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(edx, &miss); 3056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3057a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org if (right() == CompareICState::SMI) { 3058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotSmi(eax, &miss); 3059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Inlining the double comparison and falling back to the general compare 3062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // stub if NaN is involved or SSE2 or CMOV is unsupported. 3063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, edx); 3064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(ecx, eax); 3065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(ecx, &generic_stub, Label::kNear); 3066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 3068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate()->factory()->heap_number_map()); 3069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &maybe_undefined1, Label::kNear); 3070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 3071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate()->factory()->heap_number_map()); 3072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &maybe_undefined2, Label::kNear); 3073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&unordered); 3075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&generic_stub); 3076a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org CompareICStub stub(isolate(), op(), CompareICState::GENERIC, 3077a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org CompareICState::GENERIC, CompareICState::GENERIC); 3078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); 3079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&maybe_undefined1); 308121d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org if (Token::IsOrderedRelationalCompareOp(op())) { 3082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); 3083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &miss); 3084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(edx, &unordered); 3085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); 3086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &maybe_undefined2, Label::kNear); 3087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&unordered); 3088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&maybe_undefined2); 309121d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org if (Token::IsOrderedRelationalCompareOp(op())) { 3092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); 3093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &unordered); 3094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 3097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateMiss(masm); 3098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 310142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.orgvoid CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { 3102a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org DCHECK(state() == CompareICState::INTERNALIZED_STRING); 3103e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(GetCondition() == equal); 3104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Registers containing left and right operands respectively. 3106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register left = edx; 3107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register right = eax; 3108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register tmp1 = ecx; 3109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register tmp2 = ebx; 3110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that both operands are heap objects. 3112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label miss; 3113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(tmp1, left); 3114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 3115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(tmp1, right); 3116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(tmp1, &miss, Label::kNear); 3117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that both operands are internalized strings. 3119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 3120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 3121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 3122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 3123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 3124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ or_(tmp1, tmp2); 3125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); 3126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &miss, Label::kNear); 3127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Internalized strings are compared by identity. 3129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label done; 3130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(left, right); 3131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Make sure eax is non-zero. At this point input operands are 3132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // guaranteed to be non-zero. 3133e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(right.is(eax)); 3134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &done, Label::kNear); 3135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(EQUAL == 0); 3136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 3137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(EQUAL))); 3138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 3139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 3142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateMiss(masm); 3143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 314642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.orgvoid CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { 3147a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org DCHECK(state() == CompareICState::UNIQUE_NAME); 3148e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(GetCondition() == equal); 3149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Registers containing left and right operands respectively. 3151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register left = edx; 3152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register right = eax; 3153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register tmp1 = ecx; 3154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register tmp2 = ebx; 3155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that both operands are heap objects. 3157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label miss; 3158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(tmp1, left); 3159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 3160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(tmp1, right); 3161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(tmp1, &miss, Label::kNear); 3162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that both operands are unique names. This leaves the instance 3164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // types loaded in tmp1 and tmp2. 3165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 3166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 3167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 3168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 3169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 317006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ JumpIfNotUniqueNameInstanceType(tmp1, &miss, Label::kNear); 317106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ JumpIfNotUniqueNameInstanceType(tmp2, &miss, Label::kNear); 3172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Unique names are compared by identity. 3174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label done; 3175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(left, right); 3176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Make sure eax is non-zero. At this point input operands are 3177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // guaranteed to be non-zero. 3178e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(right.is(eax)); 3179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &done, Label::kNear); 3180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(EQUAL == 0); 3181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 3182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(EQUAL))); 3183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 3184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 3187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateMiss(masm); 3188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 319142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.orgvoid CompareICStub::GenerateStrings(MacroAssembler* masm) { 3192a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org DCHECK(state() == CompareICState::STRING); 3193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label miss; 3194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 319521d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org bool equality = Token::IsEqualityOp(op()); 3196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Registers containing left and right operands respectively. 3198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register left = edx; 3199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register right = eax; 3200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register tmp1 = ecx; 3201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register tmp2 = ebx; 3202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register tmp3 = edi; 3203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that both operands are heap objects. 3205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(tmp1, left); 3206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 3207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(tmp1, right); 3208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(tmp1, &miss); 3209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that both operands are strings. This leaves the instance 3211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // types loaded in tmp1 and tmp2. 3212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 3213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 3214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 3215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 3216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(tmp3, tmp1); 3217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kNotStringTag != 0); 3218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ or_(tmp3, tmp2); 3219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(tmp3, Immediate(kIsNotStringMask)); 3220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &miss); 3221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Fast check for identical strings. 3223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label not_same; 3224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(left, right); 3225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, ¬_same, Label::kNear); 3226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(EQUAL == 0); 3227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kSmiTag == 0); 3228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(eax, Immediate(Smi::FromInt(EQUAL))); 3229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Handle not identical strings. 3232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_same); 3233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check that both strings are internalized. If they are, we're done 3235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // because we already know they are not identical. But in the case of 3236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // non-equality compare, we still need to determine the order. We 3237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // also know they are both strings. 3238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (equality) { 3239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label do_compare; 3240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(kInternalizedTag == 0); 3241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ or_(tmp1, tmp2); 3242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(tmp1, Immediate(kIsNotInternalizedMask)); 3243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &do_compare, Label::kNear); 3244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Make sure eax is non-zero. At this point input operands are 3245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // guaranteed to be non-zero. 3246e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(right.is(eax)); 3247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&do_compare); 3249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3251b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org // Check that both strings are sequential one-byte. 3252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label runtime; 3253b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org __ JumpIfNotBothSequentialOneByteStrings(left, right, tmp1, tmp2, &runtime); 3254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3255b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org // Compare flat one byte strings. Returns when done. 3256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (equality) { 3257b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, 3258b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org tmp2); 3259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 3260b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1, 3261b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org tmp2, tmp3); 3262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Handle more complex cases in runtime. 3265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&runtime); 3266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(tmp1); // Return address. 3267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(left); 3268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(right); 3269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(tmp1); 3270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (equality) { 3271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallRuntime(Runtime::kStringEquals, 2, 1); 3272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 327347390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 3274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 3277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateMiss(masm); 3278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 328142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.orgvoid CompareICStub::GenerateObjects(MacroAssembler* masm) { 3282a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org DCHECK(state() == CompareICState::OBJECT); 3283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label miss; 3284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, edx); 3285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(ecx, eax); 3286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(ecx, &miss, Label::kNear); 3287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); 3289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &miss, Label::kNear); 3290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); 3291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &miss, Label::kNear); 3292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3293e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(GetCondition() == equal); 3294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(eax, edx); 3295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 3298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateMiss(masm); 3299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 330242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.orgvoid CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { 3303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label miss; 3304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, edx); 3305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(ecx, eax); 3306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(ecx, &miss, Label::kNear); 3307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 3309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 3310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, known_map_); 3311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &miss, Label::kNear); 3312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ebx, known_map_); 3313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &miss, Label::kNear); 3314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(eax, edx); 3316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&miss); 3319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateMiss(masm); 3320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 332342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.orgvoid CompareICStub::GenerateMiss(MacroAssembler* masm) { 3324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org { 3325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Call the runtime system in a fresh internal frame. 3326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), 3327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate()); 3328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 3329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); // Preserve edx and eax. 3330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(eax); 3331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); // And also use them as the arguments. 3332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(eax); 333321d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org __ push(Immediate(Smi::FromInt(op()))); 3334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CallExternalReference(miss, 3); 3335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compute the entry point of the rewritten stub. 3336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); 3337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(eax); 3338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edx); 3339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Do a tail call to the rewritten stub. 3342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(edi); 3343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Helper function used to check that the dictionary doesn't contain 3347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// the property. This function may return false negatives, so miss_label 3348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// must always call a backup property check that is complete. 3349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// This function is safe to call if the receiver has fast properties. 3350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Name must be a unique name and receiver must be a heap object. 3351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, 3352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* miss, 3353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* done, 3354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register properties, 3355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Handle<Name> name, 3356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register r0) { 3357e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(name->IsUniqueName()); 3358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If names of slots in range from 1 to kProbes - 1 for the hash value are 3360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // not equal to the name and kProbes-th slot is not used (its name is the 3361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // undefined value), it guarantees the hash table doesn't contain the 3362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // property. It's true even if some slots represent deleted properties 3363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (their names are the hole value). 3364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org for (int i = 0; i < kInlinedProbes; i++) { 3365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compute the masked index: (hash + i + i * i) & mask. 3366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register index = r0; 3367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Capacity is smi 2^n. 3368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(index, FieldOperand(properties, kCapacityOffset)); 3369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ dec(index); 3370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(index, 3371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(Smi::FromInt(name->Hash() + 3372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org NameDictionary::GetProbeOffset(i)))); 3373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Scale the index by multiplying by the entry size. 3375e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(NameDictionary::kEntrySize == 3); 3376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. 3377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register entity_name = r0; 3378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Having undefined at this place means the name is not contained. 3379e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(kSmiTagSize, 1); 3380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(entity_name, Operand(properties, index, times_half_pointer_size, 3381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kElementsStartOffset - kHeapObjectTag)); 3382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(entity_name, masm->isolate()->factory()->undefined_value()); 3383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, done); 3384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Stop if found the property. 3386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(entity_name, Handle<Name>(name)); 3387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, miss); 3388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label good; 3390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check for the hole and skip. 3391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(entity_name, masm->isolate()->factory()->the_hole_value()); 3392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &good, Label::kNear); 3393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check if the entry name is not a unique name. 3395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); 339606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ JumpIfNotUniqueNameInstanceType( 339706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org FieldOperand(entity_name, Map::kInstanceTypeOffset), miss); 3398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&good); 3399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org NameDictionaryLookupStub stub(masm->isolate(), properties, r0, r0, 3402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org NEGATIVE_LOOKUP); 3403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Immediate(Handle<Object>(name))); 3404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Immediate(name->Hash())); 3405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CallStub(&stub); 3406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(r0, r0); 3407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, miss); 3408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(done); 3409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Probe the name dictionary in the |elements| register. Jump to the 3413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// |done| label if a property with the given name is found leaving the 3414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// index into the dictionary in |r0|. Jump to the |miss| label 3415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// otherwise. 3416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, 3417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* miss, 3418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label* done, 3419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register elements, 3420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register name, 3421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register r0, 3422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register r1) { 3423e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!elements.is(r0)); 3424e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!elements.is(r1)); 3425e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!name.is(r0)); 3426e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!name.is(r1)); 3427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ AssertName(name); 3429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(r1, FieldOperand(elements, kCapacityOffset)); 3431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ shr(r1, kSmiTagSize); // convert smi to int 3432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ dec(r1); 3433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Generate an unrolled loop that performs a few probes before 3435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // giving up. Measurements done on Gmail indicate that 2 probes 3436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // cover ~93% of loads from dictionaries. 3437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org for (int i = 0; i < kInlinedProbes; i++) { 3438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compute the masked index: (hash + i + i * i) & mask. 3439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(r0, FieldOperand(name, Name::kHashFieldOffset)); 3440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ shr(r0, Name::kHashShift); 3441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (i > 0) { 3442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(r0, Immediate(NameDictionary::GetProbeOffset(i))); 3443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(r0, r1); 3445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Scale the index by multiplying by the entry size. 3447e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(NameDictionary::kEntrySize == 3); 3448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(r0, Operand(r0, r0, times_2, 0)); // r0 = r0 * 3 3449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check if the key is identical to the name. 3451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(name, Operand(elements, 3452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org r0, 3453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org times_4, 3454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kElementsStartOffset - kHeapObjectTag)); 3455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, done); 3456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org NameDictionaryLookupStub stub(masm->isolate(), elements, r1, r0, 3459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org POSITIVE_LOOKUP); 3460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(name); 3461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(r0, FieldOperand(name, Name::kHashFieldOffset)); 3462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ shr(r0, Name::kHashShift); 3463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(r0); 3464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CallStub(&stub); 3465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(r1, r1); 3467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, miss); 3468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(done); 3469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid NameDictionaryLookupStub::Generate(MacroAssembler* masm) { 3473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // This stub overrides SometimesSetsUpAFrame() to return false. That means 3474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // we cannot call anything that could cause a GC from this stub. 3475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Stack frame on entry: 3476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0 * kPointerSize]: return address. 3477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[1 * kPointerSize]: key's hash. 3478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[2 * kPointerSize]: key. 3479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Registers: 3480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // dictionary_: NameDictionary to probe. 3481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // result_: used as scratch. 3482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // index_: will hold an index of entry if lookup is successful. 3483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // might alias with result_. 3484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Returns: 3485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // result_ is zero if lookup failed, non zero otherwise. 3486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label in_dictionary, maybe_in_dictionary, not_in_dictionary; 3488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 348942ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org Register scratch = result(); 3490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 349142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org __ mov(scratch, FieldOperand(dictionary(), kCapacityOffset)); 3492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ dec(scratch); 3493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(scratch); 3494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(scratch); 3495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If names of slots in range from 1 to kProbes - 1 for the hash value are 3497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // not equal to the name and kProbes-th slot is not used (its name is the 3498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // undefined value), it guarantees the hash table doesn't contain the 3499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // property. It's true even if some slots represent deleted properties 3500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // (their names are the null value). 3501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org for (int i = kInlinedProbes; i < kTotalProbes; i++) { 3502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Compute the masked index: (hash + i + i * i) & mask. 3503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, Operand(esp, 2 * kPointerSize)); 3504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (i > 0) { 3505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(scratch, Immediate(NameDictionary::GetProbeOffset(i))); 3506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(scratch, Operand(esp, 0)); 3508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Scale the index by multiplying by the entry size. 3510e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(NameDictionary::kEntrySize == 3); 351142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org __ lea(index(), Operand(scratch, scratch, times_2, 0)); // index *= 3. 3512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Having undefined at this place means the name is not contained. 3514e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(kSmiTagSize, 1); 351542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org __ mov(scratch, Operand(dictionary(), index(), times_pointer_size, 3516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kElementsStartOffset - kHeapObjectTag)); 3517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(scratch, isolate()->factory()->undefined_value()); 3518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, ¬_in_dictionary); 3519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Stop if found the property. 3521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(scratch, Operand(esp, 3 * kPointerSize)); 3522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &in_dictionary); 3523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 352442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) { 3525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If we hit a key that is not a unique name during negative 3526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // lookup we have to bailout as this key might be equal to the 3527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // key we are looking for. 3528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check if the entry name is not a unique name. 3530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 353106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ JumpIfNotUniqueNameInstanceType( 353206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org FieldOperand(scratch, Map::kInstanceTypeOffset), 353306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org &maybe_in_dictionary); 3534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&maybe_in_dictionary); 3538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If we are doing negative lookup then probing failure should be 3539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // treated as a lookup success. For positive lookup probing failure 3540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // should be treated as lookup failure. 354142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org if (mode() == POSITIVE_LOOKUP) { 354242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org __ mov(result(), Immediate(0)); 3543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Drop(1); 3544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(2 * kPointerSize); 3545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&in_dictionary); 354842ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org __ mov(result(), Immediate(1)); 3549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Drop(1); 3550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(2 * kPointerSize); 3551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_in_dictionary); 355342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org __ mov(result(), Immediate(0)); 3554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Drop(1); 3555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(2 * kPointerSize); 3556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 3560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Isolate* isolate) { 356142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org StoreBufferOverflowStub stub(isolate, kDontSaveFPRegs); 3562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stub.GetCode(); 356306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org StoreBufferOverflowStub stub2(isolate, kSaveFPRegs); 356406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org stub2.GetCode(); 3565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Takes the input in 3 registers: address_ value_ and object_. A pointer to 3569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// the value has just been written into the object, now this stub makes sure 3570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// we keep the GC informed. The word in the object where the value has been 3571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// written is in the address register. 3572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid RecordWriteStub::Generate(MacroAssembler* masm) { 3573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label skip_to_incremental_noncompacting; 3574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label skip_to_incremental_compacting; 3575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The first two instructions are generated with labels so as to get the 3577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // offset fixed up correctly by the bind(Label*) call. We patch it back and 3578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // forth between a compare instructions (a nop in this position) and the 3579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // real branch when we start and stop incremental heap marking. 3580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&skip_to_incremental_noncompacting, Label::kNear); 3581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&skip_to_incremental_compacting, Label::kFar); 3582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 358342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org if (remembered_set_action() == EMIT_REMEMBERED_SET) { 358406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 3585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MacroAssembler::kReturnAtEnd); 3586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 3587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&skip_to_incremental_noncompacting); 3591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateIncremental(masm, INCREMENTAL); 3592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&skip_to_incremental_compacting); 3594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateIncremental(masm, INCREMENTAL_COMPACTION); 3595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. 3597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Will be checked in IncrementalMarking::ActivateGeneratedStub. 3598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->set_byte_at(0, kTwoByteNopInstruction); 3599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->set_byte_at(2, kFiveByteNopInstruction); 3600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { 3604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.Save(masm); 3605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 360642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org if (remembered_set_action() == EMIT_REMEMBERED_SET) { 3607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label dont_need_remembered_set; 3608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(regs_.scratch0(), Operand(regs_.address(), 0)); 3610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. 3611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.scratch0(), 3612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org &dont_need_remembered_set); 3613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CheckPageFlag(regs_.object(), 3615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.scratch0(), 3616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 1 << MemoryChunk::SCAN_ON_SCAVENGE, 3617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org not_zero, 3618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org &dont_need_remembered_set); 3619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // First notify the incremental marker if necessary, then update the 3621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // remembered set. 3622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CheckNeedsToInformIncrementalMarker( 3623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm, 3624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, 3625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org mode); 3626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org InformIncrementalMarker(masm); 3627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.Restore(masm); 362806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 3629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MacroAssembler::kReturnAtEnd); 3630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&dont_need_remembered_set); 3632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CheckNeedsToInformIncrementalMarker( 3635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm, 3636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kReturnOnNoNeedToInformIncrementalMarker, 3637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org mode); 3638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org InformIncrementalMarker(masm); 3639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.Restore(masm); 3640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { 364506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode()); 3646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int argument_count = 3; 3647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ PrepareCallCFunction(argument_count, regs_.scratch0()); 3648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 0 * kPointerSize), regs_.object()); 3649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 1 * kPointerSize), regs_.address()); // Slot. 3650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(esp, 2 * kPointerSize), 3651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(ExternalReference::isolate_address(isolate()))); 3652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org AllowExternalCallThatCantCauseGC scope(masm); 3654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CallCFunction( 3655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference::incremental_marking_record_write_function(isolate()), 3656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org argument_count); 3657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 365806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode()); 3659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid RecordWriteStub::CheckNeedsToInformIncrementalMarker( 3663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MacroAssembler* masm, 3664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org OnNoNeedToInformIncrementalMarker on_no_need, 3665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Mode mode) { 3666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label object_is_black, need_incremental, need_incremental_pop_object; 3667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(regs_.scratch0(), Immediate(~Page::kPageAlignmentMask)); 3669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(regs_.scratch0(), regs_.object()); 3670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(regs_.scratch1(), 3671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Operand(regs_.scratch0(), 3672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MemoryChunk::kWriteBarrierCounterOffset)); 3673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(regs_.scratch1(), Immediate(1)); 3674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(regs_.scratch0(), 3675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MemoryChunk::kWriteBarrierCounterOffset), 3676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.scratch1()); 3677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(negative, &need_incremental); 3678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Let's look at the color of the object: If it is not black we don't have 3680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // to inform the incremental marker. 3681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfBlack(regs_.object(), 3682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.scratch0(), 3683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.scratch1(), 3684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org &object_is_black, 3685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label::kNear); 3686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.Restore(masm); 3688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 368906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 3690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MacroAssembler::kReturnAtEnd); 3691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 3692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&object_is_black); 3696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get the value from the slot. 3698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(regs_.scratch0(), Operand(regs_.address(), 0)); 3699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (mode == INCREMENTAL_COMPACTION) { 3701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label ensure_not_white; 3702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CheckPageFlag(regs_.scratch0(), // Contains value. 3704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.scratch1(), // Scratch. 3705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MemoryChunk::kEvacuationCandidateMask, 3706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org zero, 3707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org &ensure_not_white, 3708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label::kNear); 3709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CheckPageFlag(regs_.object(), 3711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.scratch1(), // Scratch. 3712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MemoryChunk::kSkipEvacuationSlotsRecordingMask, 3713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org not_zero, 3714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org &ensure_not_white, 3715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label::kNear); 3716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&need_incremental); 3718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&ensure_not_white); 3720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We need an extra register for this, so we push the object register 3723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // temporarily. 3724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(regs_.object()); 3725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ EnsureNotWhite(regs_.scratch0(), // The value. 3726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.scratch1(), // Scratch. 3727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.object(), // Scratch. 3728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org &need_incremental_pop_object, 3729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label::kNear); 3730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(regs_.object()); 3731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org regs_.Restore(masm); 3733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 373406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 3735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MacroAssembler::kReturnAtEnd); 3736864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 3737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&need_incremental_pop_object); 3741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(regs_.object()); 3742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&need_incremental); 3744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Fall through when we need to inform the incremental marker. 3746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { 3750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------- S t a t e ------------- 3751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- eax : element value to store 3752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- ecx : element index as smi 3753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[0] : return address 3754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[4] : array literal index in function 3755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[8] : array literal 3756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // clobbers ebx, edx, edi 3757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------------------------------- 3758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label element_done; 3760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label double_elements; 3761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label smi_element; 3762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label slow_elements; 3763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label slow_elements_from_double; 3764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label fast_elements; 3765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Get array literal index, array literal and its map. 3767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, Operand(esp, 1 * kPointerSize)); 3768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, Operand(esp, 2 * kPointerSize)); 3769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edi, FieldOperand(ebx, JSObject::kMapOffset)); 3770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CheckFastElements(edi, &double_elements); 3772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Check for FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS elements 3774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ JumpIfSmi(eax, &smi_element); 3775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CheckFastSmiElements(edi, &fast_elements, Label::kNear); 3776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Store into the array literal requires a elements transition. Call into 3778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // the runtime. 3779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&slow_elements); 3781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edi); // Pop return address and remember to put back later for tail 3782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // call. 3783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ebx); 3784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ecx); 3785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(eax); 3786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 3787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); 3788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); 3789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edi); // Return return address so that tail call returns to right 3790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // place. 3791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1); 3792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&slow_elements_from_double); 3794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edx); 3795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(&slow_elements); 3796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object. 3798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&fast_elements); 3799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); 3800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(ecx, FieldOperand(ebx, ecx, times_half_pointer_size, 3801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArrayBase::kHeaderSize)); 3802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(Operand(ecx, 0), eax); 3803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Update the write barrier for the array store. 380406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org __ RecordWrite(ebx, ecx, eax, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 3805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org OMIT_SMI_CHECK); 3806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS, 3809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // and value is Smi. 3810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&smi_element); 3811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); 3812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(FieldOperand(ebx, ecx, times_half_pointer_size, 3813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org FixedArrayBase::kHeaderSize), eax); 3814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Array literal has ElementsKind of FAST_*_DOUBLE_ELEMENTS. 3817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&double_elements); 3818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); 3820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, FieldOperand(ebx, JSObject::kElementsOffset)); 3821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ StoreNumberToDoubleElements(eax, 3822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org edx, 3823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ecx, 3824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org edi, 3825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org &slow_elements_from_double, 3826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org false); 3827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edx); 3828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid StubFailureTrampolineStub::Generate(MacroAssembler* masm) { 383306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org CEntryStub ces(isolate(), 1, kSaveFPRegs); 3834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ call(ces.GetCode(), RelocInfo::CODE_TARGET); 3835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int parameter_count_offset = 3836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; 3837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ebx, MemOperand(ebp, parameter_count_offset)); 3838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); 3839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ecx); 38407b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org int additional_offset = 38417b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org function_mode() == JS_FUNCTION_STUB_MODE ? kPointerSize : 0; 3842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset)); 3843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ jmp(ecx); // Return to IC Miss stub, continuation still on stack. 3844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 38477b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.orgvoid LoadICTrampolineStub::Generate(MacroAssembler* masm) { 384842ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); 38497b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org VectorLoadStub stub(isolate(), state()); 38507b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); 38517b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org} 38527b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org 38537b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org 38547b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.orgvoid KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { 385542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); 38567b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org VectorKeyedLoadStub stub(isolate()); 38577b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); 38587b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org} 38597b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org 38607b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org 3861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { 3862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (masm->isolate()->function_entry_hook() != NULL) { 3863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ProfileEntryHookStub stub(masm->isolate()); 3864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->CallStub(&stub); 3865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid ProfileEntryHookStub::Generate(MacroAssembler* masm) { 3870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Save volatile registers. 3871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org const int kNumSavedRegisters = 3; 3872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(eax); 3873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(ecx); 3874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(edx); 3875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Calculate and push the original stack pointer. 3877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize)); 3878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(eax); 3879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Retrieve our return address and use it to calculate the calling 3881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // function's address. 3882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize)); 3883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ sub(eax, Immediate(Assembler::kCallInstructionLength)); 3884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(eax); 3885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Call the entry hook. 3887e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(isolate()->function_entry_hook() != NULL); 3888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ call(FUNCTION_ADDR(isolate()->function_entry_hook()), 3889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org RelocInfo::RUNTIME_ENTRY); 3890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(esp, Immediate(2 * kPointerSize)); 3891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Restore ecx. 3893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(edx); 3894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(ecx); 3895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(eax); 3896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ ret(0); 3898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgtemplate<class T> 3902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void CreateArrayDispatch(MacroAssembler* masm, 3903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org AllocationSiteOverrideMode mode) { 3904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (mode == DISABLE_ALLOCATION_SITES) { 3905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org T stub(masm->isolate(), 3906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GetInitialFastElementsKind(), 3907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org mode); 3908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallStub(&stub); 3909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else if (mode == DONT_OVERRIDE) { 3910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int last_index = GetSequenceIndexFromFastElementsKind( 3911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org TERMINAL_FAST_ELEMENTS_KIND); 3912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org for (int i = 0; i <= last_index; ++i) { 3913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label next; 3914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 3915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edx, kind); 3916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &next); 3917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org T stub(masm->isolate(), kind); 3918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallStub(&stub); 3919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&next); 3920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If we reached this point there is a problem. 3923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Abort(kUnexpectedElementsKindInArrayConstructor); 3924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 3925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org UNREACHABLE(); 3926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 3928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void CreateArrayDispatchOneArgument(MacroAssembler* masm, 3931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org AllocationSiteOverrideMode mode) { 3932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ebx - allocation site (if mode != DISABLE_ALLOCATION_SITES) 3933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edx - kind (if mode != DISABLE_ALLOCATION_SITES) 3934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // eax - number of arguments 3935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // edi - constructor? 3936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[0] - return address 3937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // esp[4] - last argument 3938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label normal_sequence; 3939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (mode == DONT_OVERRIDE) { 3940e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_SMI_ELEMENTS == 0); 3941e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_HOLEY_SMI_ELEMENTS == 1); 3942e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_ELEMENTS == 2); 3943e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_HOLEY_ELEMENTS == 3); 3944e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_DOUBLE_ELEMENTS == 4); 3945e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(FAST_HOLEY_DOUBLE_ELEMENTS == 5); 3946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // is the low bit set? If so, we are holey and that is good. 3948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test_b(edx, 1); 3949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, &normal_sequence); 3950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // look at the first argument 3953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(esp, kPointerSize)); 3954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, ecx); 3955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &normal_sequence); 3956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (mode == DISABLE_ALLOCATION_SITES) { 3958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ElementsKind initial = GetInitialFastElementsKind(); 3959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ElementsKind holey_initial = GetHoleyElementsKind(initial); 3960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ArraySingleArgumentConstructorStub stub_holey(masm->isolate(), 3962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org holey_initial, 3963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org DISABLE_ALLOCATION_SITES); 3964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallStub(&stub_holey); 3965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&normal_sequence); 3967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ArraySingleArgumentConstructorStub stub(masm->isolate(), 3968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org initial, 3969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org DISABLE_ALLOCATION_SITES); 3970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallStub(&stub); 3971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else if (mode == DONT_OVERRIDE) { 3972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We are going to create a holey array, but our kind is non-holey. 3973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Fix kind and retry. 3974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ inc(edx); 3975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 3977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Handle<Map> allocation_site_map = 3978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org masm->isolate()->factory()->allocation_site_map(); 3979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(FieldOperand(ebx, 0), Immediate(allocation_site_map)); 3980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(equal, kExpectedAllocationSite); 3981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 3982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Save the resulting elements kind in type info. We can't just store r3 3984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // in the AllocationSite::transition_info field because elements kind is 3985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // restricted to a portion of the field...upper bits need to be left alone. 3986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 3987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(FieldOperand(ebx, AllocationSite::kTransitionInfoOffset), 3988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Immediate(Smi::FromInt(kFastElementsKindPackedToHoley))); 3989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 3990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&normal_sequence); 3991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int last_index = GetSequenceIndexFromFastElementsKind( 3992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org TERMINAL_FAST_ELEMENTS_KIND); 3993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org for (int i = 0; i <= last_index; ++i) { 3994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label next; 3995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 3996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(edx, kind); 3997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_equal, &next); 3998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ArraySingleArgumentConstructorStub stub(masm->isolate(), kind); 3999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallStub(&stub); 4000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&next); 4001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If we reached this point there is a problem. 4004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Abort(kUnexpectedElementsKindInArrayConstructor); 4005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 4006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org UNREACHABLE(); 4007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 4009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgtemplate<class T> 4012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { 4013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int to_index = GetSequenceIndexFromFastElementsKind( 4014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org TERMINAL_FAST_ELEMENTS_KIND); 4015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org for (int i = 0; i <= to_index; ++i) { 4016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org T stub(isolate, kind); 4018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stub.GetCode(); 4019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { 4020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org T stub1(isolate, kind, DISABLE_ALLOCATION_SITES); 4021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stub1.GetCode(); 4022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 4025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { 4028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( 4029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate); 4030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( 4031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate); 4032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( 4033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org isolate); 4034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 4035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( 4038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Isolate* isolate) { 4039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS }; 4040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org for (int i = 0; i < 2; i++) { 4041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // For internal arrays we only need a few things 4042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]); 4043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stubh1.GetCode(); 4044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]); 4045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stubh2.GetCode(); 4046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); 4047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stubh3.GetCode(); 4048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 4050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid ArrayConstructorStub::GenerateDispatchToArrayStub( 4053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MacroAssembler* masm, 4054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org AllocationSiteOverrideMode mode) { 40557b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org if (argument_count() == ANY) { 4056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label not_zero_case, not_one_case; 4057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(eax, eax); 4058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, ¬_zero_case); 4059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 4060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_zero_case); 4062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, 1); 4063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(greater, ¬_one_case); 4064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CreateArrayDispatchOneArgument(masm, mode); 4065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_one_case); 4067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 40687b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org } else if (argument_count() == NONE) { 4069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 40707b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org } else if (argument_count() == ONE) { 4071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CreateArrayDispatchOneArgument(masm, mode); 40727b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org } else if (argument_count() == MORE_THAN_ONE) { 4073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 4074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 4075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org UNREACHABLE(); 4076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 4078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid ArrayConstructorStub::Generate(MacroAssembler* masm) { 4081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------- S t a t e ------------- 40827b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org // -- eax : argc (only if argument_count() == ANY) 4083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- ebx : AllocationSite or undefined 4084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- edi : constructor 4085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[0] : return address 4086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[4] : last argument 4087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------------------------------- 4088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 4089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The array construct code is only set for the global and natives 4090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // builtin Array functions which always have maps. 4091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Initial map for the builtin Array function should be a map. 4093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 4094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Will both indicate a NULL and a Smi. 4095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, Immediate(kSmiTagMask)); 4096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); 4097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(ecx, MAP_TYPE, ecx); 4098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(equal, kUnexpectedInitialMapForArrayFunction); 4099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We should either have undefined in ebx or a valid AllocationSite 4101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ AssertUndefinedOrAllocationSite(ebx); 4102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label no_info; 4105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // If the feedback vector is the undefined value call an array constructor 4106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // that doesn't use AllocationSites. 4107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ebx, isolate()->factory()->undefined_value()); 4108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &no_info); 4109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Only look at the lower 16 bits of the transition info. 4111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(edx, FieldOperand(ebx, AllocationSite::kTransitionInfoOffset)); 4112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ SmiUntag(edx); 4113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 4114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ and_(edx, Immediate(AllocationSite::ElementsKindBits::kMask)); 4115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); 4116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&no_info); 4118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); 4119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 4120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid InternalArrayConstructorStub::GenerateCase( 4123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org MacroAssembler* masm, ElementsKind kind) { 4124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label not_zero_case, not_one_case; 4125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label normal_sequence; 4126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(eax, eax); 4128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(not_zero, ¬_zero_case); 4129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org InternalArrayNoArgumentConstructorStub stub0(isolate(), kind); 4130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallStub(&stub0); 4131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_zero_case); 4133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(eax, 1); 4134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(greater, ¬_one_case); 4135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (IsFastPackedElementsKind(kind)) { 4137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // We might need to create a holey array 4138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // look at the first argument 4139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, Operand(esp, kPointerSize)); 4140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, ecx); 4141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(zero, &normal_sequence); 4142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org InternalArraySingleArgumentConstructorStub 4144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org stub1_holey(isolate(), GetHoleyElementsKind(kind)); 4145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallStub(&stub1_holey); 4146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&normal_sequence); 4149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org InternalArraySingleArgumentConstructorStub stub1(isolate(), kind); 4150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallStub(&stub1); 4151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(¬_one_case); 4153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org InternalArrayNArgumentsConstructorStub stubN(isolate(), kind); 4154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ TailCallStub(&stubN); 4155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 4156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid InternalArrayConstructorStub::Generate(MacroAssembler* masm) { 4159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------- S t a t e ------------- 4160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- eax : argc 4161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- edi : constructor 4162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[0] : return address 4163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[4] : last argument 4164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------------------------------- 4165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 4167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // The array construct code is only set for the global and natives 4168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // builtin Array functions which always have maps. 4169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Initial map for the builtin Array function should be a map. 4171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 4172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Will both indicate a NULL and a Smi. 4173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ test(ecx, Immediate(kSmiTagMask)); 4174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); 4175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CmpObjectType(ecx, MAP_TYPE, ecx); 4176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(equal, kUnexpectedInitialMapForArrayFunction); 4177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Figure out the right elements kind 4180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 4181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Load the map's "bit field 2" into |result|. We only need the first byte, 4183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // but the following masking takes care of that anyway. 4184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); 4185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Retrieve elements_kind from bit field 2. 4186e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org __ DecodeField<Map::ElementsKindBits>(ecx); 4187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (FLAG_debug_code) { 4189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label done; 4190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, Immediate(FAST_ELEMENTS)); 4191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &done); 4192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS)); 4193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Assert(equal, 4194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kInvalidElementsKindForInternalArrayOrInternalPackedArray); 4195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&done); 4196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Label fast_elements_case; 4199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ cmp(ecx, Immediate(FAST_ELEMENTS)); 4200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ j(equal, &fast_elements_case); 4201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateCase(masm, FAST_HOLEY_ELEMENTS); 4202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ bind(&fast_elements_case); 4204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org GenerateCase(masm, FAST_ELEMENTS); 4205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 4206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid CallApiFunctionStub::Generate(MacroAssembler* masm) { 4209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------- S t a t e ------------- 4210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- eax : callee 4211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- ebx : call_data 4212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- ecx : holder 4213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- edx : api_function_address 4214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esi : context 4215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- 4216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[0] : return address 4217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[4] : last argument 4218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- ... 4219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[argc * 4] : first argument 4220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[(argc + 1) * 4] : receiver 4221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------------------------------- 4222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register callee = eax; 4224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register call_data = ebx; 4225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register holder = ecx; 4226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register api_function_address = edx; 4227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register return_address = edi; 4228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register context = esi; 4229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 42307b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org int argc = this->argc(); 42317b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org bool is_store = this->is_store(); 42327b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org bool call_data_undefined = this->call_data_undefined(); 4233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org typedef FunctionCallbackArguments FCA; 4235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(FCA::kContextSaveIndex == 6); 4237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(FCA::kCalleeIndex == 5); 4238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(FCA::kDataIndex == 4); 4239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(FCA::kReturnValueOffset == 3); 4240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 4241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(FCA::kIsolateIndex == 1); 4242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(FCA::kHolderIndex == 0); 4243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org STATIC_ASSERT(FCA::kArgsLength == 7); 4244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ pop(return_address); 4246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // context save 4248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(context); 4249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // load context from callee 4250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(context, FieldOperand(callee, JSFunction::kContextOffset)); 4251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // callee 4253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(callee); 4254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // call data 4256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(call_data); 4257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch = call_data; 4259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (!call_data_undefined) { 4260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // return value 4261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Immediate(isolate()->factory()->undefined_value())); 4262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // return value default 4263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Immediate(isolate()->factory()->undefined_value())); 4264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 4265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // return value 4266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(scratch); 4267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // return value default 4268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(scratch); 4269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // isolate 4271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(Immediate(reinterpret_cast<int>(isolate()))); 4272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // holder 4273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(holder); 4274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(scratch, esp); 4276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // return address 4278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ push(return_address); 4279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // API function gets reference to the v8::Arguments. If CPU profiler 4281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // is enabled wrapper function will be called and we need to pass 4282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // address of the callback as additional parameter, always allocate 4283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // space for it. 4284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org const int kApiArgc = 1 + 1; 4285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Allocate the v8::Arguments structure in the arguments' space since 4287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // it's not controlled by GC. 4288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org const int kApiStackSpace = 4; 4289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); 4291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // FunctionCallbackInfo::implicit_args_. 4293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ApiParameterOperand(2), scratch); 4294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(scratch, Immediate((argc + FCA::kArgsLength - 1) * kPointerSize)); 4295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // FunctionCallbackInfo::values_. 4296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ApiParameterOperand(3), scratch); 4297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // FunctionCallbackInfo::length_. 4298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(ApiParameterOperand(4), Immediate(argc)); 4299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // FunctionCallbackInfo::is_construct_call_. 4300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ Move(ApiParameterOperand(5), Immediate(0)); 4301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // v8::InvocationCallback's argument. 4303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(scratch, ApiParameterOperand(2)); 4304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ApiParameterOperand(0), scratch); 4305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference thunk_ref = 4307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference::invoke_function_callback(isolate()); 4308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Operand context_restore_operand(ebp, 4310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org (2 + FCA::kContextSaveIndex) * kPointerSize); 4311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Stores return the first js argument 4312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org int return_value_offset = 0; 4313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (is_store) { 4314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org return_value_offset = 2 + FCA::kArgsLength; 4315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } else { 4316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org return_value_offset = 2 + FCA::kReturnValueOffset; 4317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org } 4318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Operand return_value_operand(ebp, return_value_offset * kPointerSize); 4319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CallApiFunctionAndReturn(api_function_address, 4320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org thunk_ref, 4321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ApiParameterOperand(1), 4322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org argc + FCA::kArgsLength + 1, 4323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org return_value_operand, 4324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org &context_restore_operand); 4325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 4326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid CallApiGetterStub::Generate(MacroAssembler* masm) { 4329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------- S t a t e ------------- 4330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[0] : return address 4331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[4] : name 4332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- esp[8 - kArgsLength*4] : PropertyCallbackArguments object 4333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- ... 4334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // -- edx : api_function_address 4335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // ----------------------------------- 4336b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org DCHECK(edx.is(ApiGetterDescriptor::function_address())); 4337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // array for v8::Arguments::values_, handler for name and pointer 4339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // to the values (it considered as smi in GC). 4340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org const int kStackSpace = PropertyCallbackArguments::kArgsLength + 2; 4341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Allocate space for opional callback address parameter in case 4342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // CPU profiler is active. 4343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org const int kApiArgc = 2 + 1; 4344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register api_function_address = edx; 4346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Register scratch = ebx; 4347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // load address of name 4349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ lea(scratch, Operand(esp, 1 * kPointerSize)); 4350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ PrepareCallApiFunction(kApiArgc); 4352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ApiParameterOperand(0), scratch); // name. 4353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ add(scratch, Immediate(kPointerSize)); 4354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ mov(ApiParameterOperand(1), scratch); // arguments pointer. 4355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference thunk_ref = 4357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ExternalReference::invoke_accessor_getter_callback(isolate()); 4358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org __ CallApiFunctionAndReturn(api_function_address, 4360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org thunk_ref, 4361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org ApiParameterOperand(2), 4362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org kStackSpace, 4363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org Operand(ebp, 7 * kPointerSize), 4364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org NULL); 4365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} 4366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#undef __ 4369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} } // namespace v8::internal 4371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org 4372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif // V8_TARGET_ARCH_X87 4373