1/*
2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef DFGCallArrayAllocatorSlowPathGenerator_h
27#define DFGCallArrayAllocatorSlowPathGenerator_h
28
29#if ENABLE(DFG_JIT)
30
31#include "DFGCommon.h"
32#include "DFGSlowPathGenerator.h"
33#include "DFGSpeculativeJIT.h"
34#include <wtf/Vector.h>
35
36namespace JSC { namespace DFG {
37
38class CallArrayAllocatorSlowPathGenerator : public JumpingSlowPathGenerator<MacroAssembler::JumpList> {
39public:
40    CallArrayAllocatorSlowPathGenerator(
41        MacroAssembler::JumpList from, SpeculativeJIT* jit, P_JITOperation_EStZ function,
42        GPRReg resultGPR, GPRReg storageGPR, Structure* structure, size_t size)
43        : JumpingSlowPathGenerator<MacroAssembler::JumpList>(from, jit)
44        , m_function(function)
45        , m_resultGPR(resultGPR)
46        , m_storageGPR(storageGPR)
47        , m_structure(structure)
48        , m_size(size)
49    {
50        ASSERT(size < static_cast<size_t>(std::numeric_limits<int32_t>::max()));
51        jit->silentSpillAllRegistersImpl(false, m_plans, resultGPR);
52    }
53
54protected:
55    virtual void generateInternal(SpeculativeJIT* jit) override
56    {
57        linkFrom(jit);
58        for (unsigned i = 0; i < m_plans.size(); ++i)
59            jit->silentSpill(m_plans[i]);
60        jit->callOperation(m_function, m_resultGPR, m_structure, m_size);
61        GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR);
62        for (unsigned i = m_plans.size(); i--;)
63            jit->silentFill(m_plans[i], canTrample);
64        jit->m_jit.loadPtr(MacroAssembler::Address(m_resultGPR, JSObject::butterflyOffset()), m_storageGPR);
65        jumpTo(jit);
66    }
67
68private:
69    P_JITOperation_EStZ m_function;
70    GPRReg m_resultGPR;
71    GPRReg m_storageGPR;
72    Structure* m_structure;
73    size_t m_size;
74    Vector<SilentRegisterSavePlan, 2> m_plans;
75};
76
77class CallArrayAllocatorWithVariableSizeSlowPathGenerator : public JumpingSlowPathGenerator<MacroAssembler::JumpList> {
78public:
79    CallArrayAllocatorWithVariableSizeSlowPathGenerator(
80        MacroAssembler::JumpList from, SpeculativeJIT* jit, P_JITOperation_EStZ function,
81        GPRReg resultGPR, Structure* contiguousStructure, Structure* arrayStorageStructure, GPRReg sizeGPR)
82        : JumpingSlowPathGenerator<MacroAssembler::JumpList>(from, jit)
83        , m_function(function)
84        , m_resultGPR(resultGPR)
85        , m_contiguousStructure(contiguousStructure)
86        , m_arrayStorageStructure(arrayStorageStructure)
87        , m_sizeGPR(sizeGPR)
88    {
89        jit->silentSpillAllRegistersImpl(false, m_plans, resultGPR);
90    }
91
92protected:
93    virtual void generateInternal(SpeculativeJIT* jit) override
94    {
95        linkFrom(jit);
96        for (unsigned i = 0; i < m_plans.size(); ++i)
97            jit->silentSpill(m_plans[i]);
98        GPRReg scratchGPR = AssemblyHelpers::selectScratchGPR(m_sizeGPR);
99        MacroAssembler::Jump bigLength = jit->m_jit.branch32(MacroAssembler::AboveOrEqual, m_sizeGPR, MacroAssembler::TrustedImm32(MIN_SPARSE_ARRAY_INDEX));
100        jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
101        MacroAssembler::Jump done = jit->m_jit.jump();
102        bigLength.link(&jit->m_jit);
103        jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_arrayStorageStructure), scratchGPR);
104        done.link(&jit->m_jit);
105        jit->callOperation(m_function, m_resultGPR, scratchGPR, m_sizeGPR);
106        GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR);
107        for (unsigned i = m_plans.size(); i--;)
108            jit->silentFill(m_plans[i], canTrample);
109        jumpTo(jit);
110    }
111
112private:
113    P_JITOperation_EStZ m_function;
114    GPRReg m_resultGPR;
115    Structure* m_contiguousStructure;
116    Structure* m_arrayStorageStructure;
117    GPRReg m_sizeGPR;
118    Vector<SilentRegisterSavePlan, 2> m_plans;
119};
120
121} } // namespace JSC::DFG
122
123#endif // ENABLE(DFG_JIT)
124
125#endif // DFGCallArrayAllocatorSlowPathGenerator_h
126
127