1692e5dbf12901edacf14812a6fae25462920af42Steve Block/*
2692e5dbf12901edacf14812a6fae25462920af42Steve Block * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3692e5dbf12901edacf14812a6fae25462920af42Steve Block *
4692e5dbf12901edacf14812a6fae25462920af42Steve Block * Redistribution and use in source and binary forms, with or without
5692e5dbf12901edacf14812a6fae25462920af42Steve Block * modification, are permitted provided that the following conditions
6692e5dbf12901edacf14812a6fae25462920af42Steve Block * are met:
7692e5dbf12901edacf14812a6fae25462920af42Steve Block * 1. Redistributions of source code must retain the above copyright
8692e5dbf12901edacf14812a6fae25462920af42Steve Block *    notice, this list of conditions and the following disclaimer.
9692e5dbf12901edacf14812a6fae25462920af42Steve Block * 2. Redistributions in binary form must reproduce the above copyright
10692e5dbf12901edacf14812a6fae25462920af42Steve Block *    notice, this list of conditions and the following disclaimer in the
11692e5dbf12901edacf14812a6fae25462920af42Steve Block *    documentation and/or other materials provided with the distribution.
12692e5dbf12901edacf14812a6fae25462920af42Steve Block *
13692e5dbf12901edacf14812a6fae25462920af42Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14692e5dbf12901edacf14812a6fae25462920af42Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15692e5dbf12901edacf14812a6fae25462920af42Steve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16692e5dbf12901edacf14812a6fae25462920af42Steve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17692e5dbf12901edacf14812a6fae25462920af42Steve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18692e5dbf12901edacf14812a6fae25462920af42Steve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19692e5dbf12901edacf14812a6fae25462920af42Steve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20692e5dbf12901edacf14812a6fae25462920af42Steve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21692e5dbf12901edacf14812a6fae25462920af42Steve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22692e5dbf12901edacf14812a6fae25462920af42Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23692e5dbf12901edacf14812a6fae25462920af42Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24692e5dbf12901edacf14812a6fae25462920af42Steve Block */
25692e5dbf12901edacf14812a6fae25462920af42Steve Block
26692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "config.h"
27692e5dbf12901edacf14812a6fae25462920af42Steve Block
28e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#if ENABLE(JIT)
29692e5dbf12901edacf14812a6fae25462920af42Steve Block#if USE(JSVALUE32_64)
30692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "JIT.h"
31692e5dbf12901edacf14812a6fae25462920af42Steve Block
32692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "CodeBlock.h"
33692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "JITInlineMethods.h"
34692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "JITStubCall.h"
35692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "JSArray.h"
36692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "JSFunction.h"
37692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "JSPropertyNameIterator.h"
38692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "Interpreter.h"
39692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "LinkBuffer.h"
40692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "RepatchBuffer.h"
41692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "ResultType.h"
42692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "SamplingTool.h"
43692e5dbf12901edacf14812a6fae25462920af42Steve Block
44692e5dbf12901edacf14812a6fae25462920af42Steve Block#ifndef NDEBUG
45692e5dbf12901edacf14812a6fae25462920af42Steve Block#include <stdio.h>
46692e5dbf12901edacf14812a6fae25462920af42Steve Block#endif
47692e5dbf12901edacf14812a6fae25462920af42Steve Block
48692e5dbf12901edacf14812a6fae25462920af42Steve Blockusing namespace std;
49692e5dbf12901edacf14812a6fae25462920af42Steve Block
50692e5dbf12901edacf14812a6fae25462920af42Steve Blocknamespace JSC {
51692e5dbf12901edacf14812a6fae25462920af42Steve Block
52692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_put_by_index(Instruction* currentInstruction)
53692e5dbf12901edacf14812a6fae25462920af42Steve Block{
54692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[1].u.operand;
55692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[2].u.operand;
56692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned value = currentInstruction[3].u.operand;
57692e5dbf12901edacf14812a6fae25462920af42Steve Block
58692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubCall(this, cti_op_put_by_index);
59692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(base);
60692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(Imm32(property));
61692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(value);
62692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.call();
63692e5dbf12901edacf14812a6fae25462920af42Steve Block}
64692e5dbf12901edacf14812a6fae25462920af42Steve Block
65692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_put_getter(Instruction* currentInstruction)
66692e5dbf12901edacf14812a6fae25462920af42Steve Block{
67692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[1].u.operand;
68692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[2].u.operand;
69692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned function = currentInstruction[3].u.operand;
70692e5dbf12901edacf14812a6fae25462920af42Steve Block
71692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubCall(this, cti_op_put_getter);
72692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(base);
732bde8e466a4451c7319e3a072d118917957d6554Steve Block    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property)));
74692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(function);
75692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.call();
76692e5dbf12901edacf14812a6fae25462920af42Steve Block}
77692e5dbf12901edacf14812a6fae25462920af42Steve Block
78692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_put_setter(Instruction* currentInstruction)
79692e5dbf12901edacf14812a6fae25462920af42Steve Block{
80692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[1].u.operand;
81692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[2].u.operand;
82692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned function = currentInstruction[3].u.operand;
83692e5dbf12901edacf14812a6fae25462920af42Steve Block
84692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubCall(this, cti_op_put_setter);
85692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(base);
862bde8e466a4451c7319e3a072d118917957d6554Steve Block    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property)));
87692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(function);
88692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.call();
89692e5dbf12901edacf14812a6fae25462920af42Steve Block}
90692e5dbf12901edacf14812a6fae25462920af42Steve Block
91692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_del_by_id(Instruction* currentInstruction)
92692e5dbf12901edacf14812a6fae25462920af42Steve Block{
93692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned dst = currentInstruction[1].u.operand;
94692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[2].u.operand;
95692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[3].u.operand;
96692e5dbf12901edacf14812a6fae25462920af42Steve Block
97692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubCall(this, cti_op_del_by_id);
98692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(base);
992bde8e466a4451c7319e3a072d118917957d6554Steve Block    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property)));
100692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.call(dst);
101692e5dbf12901edacf14812a6fae25462920af42Steve Block}
102692e5dbf12901edacf14812a6fae25462920af42Steve Block
103692e5dbf12901edacf14812a6fae25462920af42Steve Block
104692e5dbf12901edacf14812a6fae25462920af42Steve Block#if !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
105692e5dbf12901edacf14812a6fae25462920af42Steve Block
106692e5dbf12901edacf14812a6fae25462920af42Steve Block/* ------------------------------ BEGIN: !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
107692e5dbf12901edacf14812a6fae25462920af42Steve Block
108692e5dbf12901edacf14812a6fae25462920af42Steve Block// Treat these as nops - the call will be handed as a regular get_by_id/op_call pair.
109692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_method_check(Instruction*) {}
110692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&) { ASSERT_NOT_REACHED(); }
111692e5dbf12901edacf14812a6fae25462920af42Steve Block#if ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
112692e5dbf12901edacf14812a6fae25462920af42Steve Block#error "JIT_OPTIMIZE_METHOD_CALLS requires JIT_OPTIMIZE_PROPERTY_ACCESS"
113692e5dbf12901edacf14812a6fae25462920af42Steve Block#endif
114692e5dbf12901edacf14812a6fae25462920af42Steve Block
115692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_get_by_val(Instruction* currentInstruction)
116692e5dbf12901edacf14812a6fae25462920af42Steve Block{
117692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned dst = currentInstruction[1].u.operand;
118692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[2].u.operand;
119692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[3].u.operand;
120692e5dbf12901edacf14812a6fae25462920af42Steve Block
121692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubCall(this, cti_op_get_by_val);
122692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(base);
123692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(property);
124692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.call(dst);
125692e5dbf12901edacf14812a6fae25462920af42Steve Block}
126692e5dbf12901edacf14812a6fae25462920af42Steve Block
127692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&)
128692e5dbf12901edacf14812a6fae25462920af42Steve Block{
129692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT_NOT_REACHED();
130692e5dbf12901edacf14812a6fae25462920af42Steve Block}
131692e5dbf12901edacf14812a6fae25462920af42Steve Block
132692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_put_by_val(Instruction* currentInstruction)
133692e5dbf12901edacf14812a6fae25462920af42Steve Block{
134692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[1].u.operand;
135692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[2].u.operand;
136692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned value = currentInstruction[3].u.operand;
137692e5dbf12901edacf14812a6fae25462920af42Steve Block
138692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubCall(this, cti_op_put_by_val);
139692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(base);
140692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(property);
141692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(value);
142692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.call();
143692e5dbf12901edacf14812a6fae25462920af42Steve Block}
144692e5dbf12901edacf14812a6fae25462920af42Steve Block
145692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_put_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&)
146692e5dbf12901edacf14812a6fae25462920af42Steve Block{
147692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT_NOT_REACHED();
148692e5dbf12901edacf14812a6fae25462920af42Steve Block}
149692e5dbf12901edacf14812a6fae25462920af42Steve Block
150692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_get_by_id(Instruction* currentInstruction)
151692e5dbf12901edacf14812a6fae25462920af42Steve Block{
152692e5dbf12901edacf14812a6fae25462920af42Steve Block    int dst = currentInstruction[1].u.operand;
153692e5dbf12901edacf14812a6fae25462920af42Steve Block    int base = currentInstruction[2].u.operand;
154692e5dbf12901edacf14812a6fae25462920af42Steve Block    int ident = currentInstruction[3].u.operand;
155692e5dbf12901edacf14812a6fae25462920af42Steve Block
156692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubCall(this, cti_op_get_by_id_generic);
157692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(base);
1582bde8e466a4451c7319e3a072d118917957d6554Steve Block    stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident))));
159692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.call(dst);
160692e5dbf12901edacf14812a6fae25462920af42Steve Block
161692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessInstructionIndex++;
162692e5dbf12901edacf14812a6fae25462920af42Steve Block}
163692e5dbf12901edacf14812a6fae25462920af42Steve Block
164692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&)
165692e5dbf12901edacf14812a6fae25462920af42Steve Block{
166692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessInstructionIndex++;
167692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT_NOT_REACHED();
168692e5dbf12901edacf14812a6fae25462920af42Steve Block}
169692e5dbf12901edacf14812a6fae25462920af42Steve Block
170692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_put_by_id(Instruction* currentInstruction)
171692e5dbf12901edacf14812a6fae25462920af42Steve Block{
172692e5dbf12901edacf14812a6fae25462920af42Steve Block    int base = currentInstruction[1].u.operand;
173692e5dbf12901edacf14812a6fae25462920af42Steve Block    int ident = currentInstruction[2].u.operand;
174692e5dbf12901edacf14812a6fae25462920af42Steve Block    int value = currentInstruction[3].u.operand;
175692e5dbf12901edacf14812a6fae25462920af42Steve Block
176692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubCall(this, cti_op_put_by_id_generic);
177692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(base);
1782bde8e466a4451c7319e3a072d118917957d6554Steve Block    stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident))));
179692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(value);
180692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.call();
181692e5dbf12901edacf14812a6fae25462920af42Steve Block
182692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessInstructionIndex++;
183692e5dbf12901edacf14812a6fae25462920af42Steve Block}
184692e5dbf12901edacf14812a6fae25462920af42Steve Block
185692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_put_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&)
186692e5dbf12901edacf14812a6fae25462920af42Steve Block{
187692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessInstructionIndex++;
188692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT_NOT_REACHED();
189692e5dbf12901edacf14812a6fae25462920af42Steve Block}
190692e5dbf12901edacf14812a6fae25462920af42Steve Block
191692e5dbf12901edacf14812a6fae25462920af42Steve Block#else // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
192692e5dbf12901edacf14812a6fae25462920af42Steve Block
193692e5dbf12901edacf14812a6fae25462920af42Steve Block/* ------------------------------ BEGIN: ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
194692e5dbf12901edacf14812a6fae25462920af42Steve Block
195692e5dbf12901edacf14812a6fae25462920af42Steve Block#if ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
196692e5dbf12901edacf14812a6fae25462920af42Steve Block
197692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_method_check(Instruction* currentInstruction)
198692e5dbf12901edacf14812a6fae25462920af42Steve Block{
199692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Assert that the following instruction is a get_by_id.
200692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT(m_interpreter->getOpcodeID((currentInstruction + OPCODE_LENGTH(op_method_check))->u.opcode) == op_get_by_id);
201692e5dbf12901edacf14812a6fae25462920af42Steve Block
202692e5dbf12901edacf14812a6fae25462920af42Steve Block    currentInstruction += OPCODE_LENGTH(op_method_check);
203692e5dbf12901edacf14812a6fae25462920af42Steve Block
204692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Do the method check - check the object & its prototype's structure inline (this is the common case).
205692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_propertyAccessInstructionIndex));
206692e5dbf12901edacf14812a6fae25462920af42Steve Block    MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
207692e5dbf12901edacf14812a6fae25462920af42Steve Block
208692e5dbf12901edacf14812a6fae25462920af42Steve Block    int dst = currentInstruction[1].u.operand;
209692e5dbf12901edacf14812a6fae25462920af42Steve Block    int base = currentInstruction[2].u.operand;
210692e5dbf12901edacf14812a6fae25462920af42Steve Block
211692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitLoad(base, regT1, regT0);
212692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitJumpSlowCaseIfNotJSCell(base, regT1);
213692e5dbf12901edacf14812a6fae25462920af42Steve Block
214692e5dbf12901edacf14812a6fae25462920af42Steve Block    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
215692e5dbf12901edacf14812a6fae25462920af42Steve Block
2162bde8e466a4451c7319e3a072d118917957d6554Steve Block    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), info.structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
2172bde8e466a4451c7319e3a072d118917957d6554Steve Block    DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(TrustedImmPtr(0), regT2);
2182bde8e466a4451c7319e3a072d118917957d6554Steve Block    Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT2, JSCell::structureOffset()), protoStructureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
219692e5dbf12901edacf14812a6fae25462920af42Steve Block
220692e5dbf12901edacf14812a6fae25462920af42Steve Block    // This will be relinked to load the function without doing a load.
2212bde8e466a4451c7319e3a072d118917957d6554Steve Block    DataLabelPtr putFunction = moveWithPatch(TrustedImmPtr(0), regT0);
222692e5dbf12901edacf14812a6fae25462920af42Steve Block
223692e5dbf12901edacf14812a6fae25462920af42Steve Block    END_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
224692e5dbf12901edacf14812a6fae25462920af42Steve Block
2252bde8e466a4451c7319e3a072d118917957d6554Steve Block    move(TrustedImm32(JSValue::CellTag), regT1);
226692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump match = jump();
227692e5dbf12901edacf14812a6fae25462920af42Steve Block
22881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoObj), patchOffsetMethodCheckProtoObj);
22981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoStructureToCompare), patchOffsetMethodCheckProtoStruct);
23081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, putFunction), patchOffsetMethodCheckPutFunction);
231692e5dbf12901edacf14812a6fae25462920af42Steve Block
232692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Link the failure cases here.
233692e5dbf12901edacf14812a6fae25462920af42Steve Block    structureCheck.link(this);
234692e5dbf12901edacf14812a6fae25462920af42Steve Block    protoStructureCheck.link(this);
235692e5dbf12901edacf14812a6fae25462920af42Steve Block
236692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Do a regular(ish) get_by_id (the slow case will be link to
237692e5dbf12901edacf14812a6fae25462920af42Steve Block    // cti_op_get_by_id_method_check instead of cti_op_get_by_id.
238692e5dbf12901edacf14812a6fae25462920af42Steve Block    compileGetByIdHotPath();
239692e5dbf12901edacf14812a6fae25462920af42Steve Block
240692e5dbf12901edacf14812a6fae25462920af42Steve Block    match.link(this);
241692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitStore(dst, regT1, regT0);
242e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    map(m_bytecodeOffset + OPCODE_LENGTH(op_method_check), dst, regT1, regT0);
243692e5dbf12901edacf14812a6fae25462920af42Steve Block
244692e5dbf12901edacf14812a6fae25462920af42Steve Block    // We've already generated the following get_by_id, so make sure it's skipped over.
245e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
246692e5dbf12901edacf14812a6fae25462920af42Steve Block}
247692e5dbf12901edacf14812a6fae25462920af42Steve Block
248692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
249692e5dbf12901edacf14812a6fae25462920af42Steve Block{
250692e5dbf12901edacf14812a6fae25462920af42Steve Block    currentInstruction += OPCODE_LENGTH(op_method_check);
251692e5dbf12901edacf14812a6fae25462920af42Steve Block
252692e5dbf12901edacf14812a6fae25462920af42Steve Block    int dst = currentInstruction[1].u.operand;
253692e5dbf12901edacf14812a6fae25462920af42Steve Block    int base = currentInstruction[2].u.operand;
254692e5dbf12901edacf14812a6fae25462920af42Steve Block    int ident = currentInstruction[3].u.operand;
255692e5dbf12901edacf14812a6fae25462920af42Steve Block
256692e5dbf12901edacf14812a6fae25462920af42Steve Block    compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter, true);
257692e5dbf12901edacf14812a6fae25462920af42Steve Block
258692e5dbf12901edacf14812a6fae25462920af42Steve Block    // We've already generated the following get_by_id, so make sure it's skipped over.
259e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
260692e5dbf12901edacf14812a6fae25462920af42Steve Block}
261692e5dbf12901edacf14812a6fae25462920af42Steve Block
262692e5dbf12901edacf14812a6fae25462920af42Steve Block#else //!ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
263692e5dbf12901edacf14812a6fae25462920af42Steve Block
264692e5dbf12901edacf14812a6fae25462920af42Steve Block// Treat these as nops - the call will be handed as a regular get_by_id/op_call pair.
265692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_method_check(Instruction*) {}
266692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&) { ASSERT_NOT_REACHED(); }
267692e5dbf12901edacf14812a6fae25462920af42Steve Block
268692e5dbf12901edacf14812a6fae25462920af42Steve Block#endif
269692e5dbf12901edacf14812a6fae25462920af42Steve Block
270e78cbe89e6f337f2f1fe40315be88f742b547151Steve BlockJIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool)
2716c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{
2726c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    JSInterfaceJIT jit;
2736c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    JumpList failures;
2742bde8e466a4451c7319e3a072d118917957d6554Steve Block    failures.append(jit.branchPtr(NotEqual, Address(regT0), TrustedImmPtr(globalData->jsStringVPtr)));
2756c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    failures.append(jit.branchTest32(NonZero, Address(regT0, OBJECT_OFFSETOF(JSString, m_fiberCount))));
2766c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
2776c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    // Load string length to regT1, and start the process of loading the data pointer into regT0
2786c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    jit.load32(Address(regT0, ThunkHelpers::jsStringLengthOffset()), regT1);
2796c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    jit.loadPtr(Address(regT0, ThunkHelpers::jsStringValueOffset()), regT0);
2806c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    jit.loadPtr(Address(regT0, ThunkHelpers::stringImplDataOffset()), regT0);
2816c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
2826c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    // Do an unsigned compare to simultaneously filter negative indices as well as indices that are too large
2836c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    failures.append(jit.branch32(AboveOrEqual, regT2, regT1));
2846c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
2856c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    // Load the character
2866c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    jit.load16(BaseIndex(regT0, regT2, TimesTwo, 0), regT0);
2876c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
2882bde8e466a4451c7319e3a072d118917957d6554Steve Block    failures.append(jit.branch32(AboveOrEqual, regT0, TrustedImm32(0x100)));
2892bde8e466a4451c7319e3a072d118917957d6554Steve Block    jit.move(TrustedImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1);
2906c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    jit.loadPtr(BaseIndex(regT1, regT0, ScalePtr, 0), regT0);
2912bde8e466a4451c7319e3a072d118917957d6554Steve Block    jit.move(TrustedImm32(JSValue::CellTag), regT1); // We null check regT0 on return so this is safe
2926c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    jit.ret();
2936c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
2946c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    failures.link(&jit);
2952bde8e466a4451c7319e3a072d118917957d6554Steve Block    jit.move(TrustedImm32(0), regT0);
2966c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    jit.ret();
2976c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
298dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    LinkBuffer patchBuffer(&jit, pool, 0);
299e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    return patchBuffer.finalizeCode().m_code;
3006c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen}
3016c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
302692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_get_by_val(Instruction* currentInstruction)
303692e5dbf12901edacf14812a6fae25462920af42Steve Block{
304692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned dst = currentInstruction[1].u.operand;
305692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[2].u.operand;
306692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[3].u.operand;
307692e5dbf12901edacf14812a6fae25462920af42Steve Block
308692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitLoad2(base, regT1, regT0, property, regT3, regT2);
309692e5dbf12901edacf14812a6fae25462920af42Steve Block
3102bde8e466a4451c7319e3a072d118917957d6554Steve Block    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
311692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitJumpSlowCaseIfNotJSCell(base, regT1);
3122bde8e466a4451c7319e3a072d118917957d6554Steve Block    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
313692e5dbf12901edacf14812a6fae25462920af42Steve Block
3142bde8e466a4451c7319e3a072d118917957d6554Steve Block    loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
3152bde8e466a4451c7319e3a072d118917957d6554Steve Block    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
316692e5dbf12901edacf14812a6fae25462920af42Steve Block
317dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
318dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
3192bde8e466a4451c7319e3a072d118917957d6554Steve Block    addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
320692e5dbf12901edacf14812a6fae25462920af42Steve Block
321692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitStore(dst, regT1, regT0);
322e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0);
323692e5dbf12901edacf14812a6fae25462920af42Steve Block}
324692e5dbf12901edacf14812a6fae25462920af42Steve Block
325692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
326692e5dbf12901edacf14812a6fae25462920af42Steve Block{
327692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned dst = currentInstruction[1].u.operand;
328692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[2].u.operand;
329692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[3].u.operand;
330692e5dbf12901edacf14812a6fae25462920af42Steve Block
331692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter); // property int32 check
332692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCaseIfNotJSCell(iter, base); // base cell check
3336c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
3346c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    Jump nonCell = jump();
335692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter); // base array check
3362bde8e466a4451c7319e3a072d118917957d6554Steve Block    Jump notString = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr));
337e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    emitNakedCall(m_globalData->getCTIStub(stringGetByValStubGenerator));
3386c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    Jump failed = branchTestPtr(Zero, regT0);
3396c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    emitStore(dst, regT1, regT0);
3406c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
3416c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    failed.link(this);
3426c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    notString.link(this);
3436c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    nonCell.link(this);
3446c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
345692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter); // vector length check
346692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter); // empty value
347692e5dbf12901edacf14812a6fae25462920af42Steve Block
348692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubCall(this, cti_op_get_by_val);
349692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(base);
350692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(property);
351692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.call(dst);
352692e5dbf12901edacf14812a6fae25462920af42Steve Block}
353692e5dbf12901edacf14812a6fae25462920af42Steve Block
354692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_put_by_val(Instruction* currentInstruction)
355692e5dbf12901edacf14812a6fae25462920af42Steve Block{
356692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[1].u.operand;
357692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[2].u.operand;
358692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned value = currentInstruction[3].u.operand;
359692e5dbf12901edacf14812a6fae25462920af42Steve Block
360692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitLoad2(base, regT1, regT0, property, regT3, regT2);
361692e5dbf12901edacf14812a6fae25462920af42Steve Block
3622bde8e466a4451c7319e3a072d118917957d6554Steve Block    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
363692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitJumpSlowCaseIfNotJSCell(base, regT1);
3642bde8e466a4451c7319e3a072d118917957d6554Steve Block    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
3652bde8e466a4451c7319e3a072d118917957d6554Steve Block    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
366692e5dbf12901edacf14812a6fae25462920af42Steve Block
3672bde8e466a4451c7319e3a072d118917957d6554Steve Block    loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
368692e5dbf12901edacf14812a6fae25462920af42Steve Block
3692bde8e466a4451c7319e3a072d118917957d6554Steve Block    Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
370692e5dbf12901edacf14812a6fae25462920af42Steve Block
371692e5dbf12901edacf14812a6fae25462920af42Steve Block    Label storeResult(this);
372692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitLoad(value, regT1, regT0);
373dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); // payload
374dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); // tag
375692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump end = jump();
376692e5dbf12901edacf14812a6fae25462920af42Steve Block
377692e5dbf12901edacf14812a6fae25462920af42Steve Block    empty.link(this);
3782bde8e466a4451c7319e3a072d118917957d6554Steve Block    add32(TrustedImm32(1), Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
379dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    branch32(Below, regT2, Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_length))).linkTo(storeResult, this);
380692e5dbf12901edacf14812a6fae25462920af42Steve Block
3812bde8e466a4451c7319e3a072d118917957d6554Steve Block    add32(TrustedImm32(1), regT2, regT0);
382dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    store32(regT0, Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_length)));
383692e5dbf12901edacf14812a6fae25462920af42Steve Block    jump().linkTo(storeResult, this);
384692e5dbf12901edacf14812a6fae25462920af42Steve Block
385692e5dbf12901edacf14812a6fae25462920af42Steve Block    end.link(this);
386692e5dbf12901edacf14812a6fae25462920af42Steve Block}
387692e5dbf12901edacf14812a6fae25462920af42Steve Block
388692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
389692e5dbf12901edacf14812a6fae25462920af42Steve Block{
390692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[1].u.operand;
391692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[2].u.operand;
392692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned value = currentInstruction[3].u.operand;
393692e5dbf12901edacf14812a6fae25462920af42Steve Block
394692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter); // property int32 check
395692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCaseIfNotJSCell(iter, base); // base cell check
396692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter); // base not array check
397692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter); // in vector check
398692e5dbf12901edacf14812a6fae25462920af42Steve Block
399692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubPutByValCall(this, cti_op_put_by_val);
400692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubPutByValCall.addArgument(base);
401692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubPutByValCall.addArgument(property);
402692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubPutByValCall.addArgument(value);
403692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubPutByValCall.call();
404692e5dbf12901edacf14812a6fae25462920af42Steve Block}
405692e5dbf12901edacf14812a6fae25462920af42Steve Block
406692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_get_by_id(Instruction* currentInstruction)
407692e5dbf12901edacf14812a6fae25462920af42Steve Block{
408692e5dbf12901edacf14812a6fae25462920af42Steve Block    int dst = currentInstruction[1].u.operand;
409692e5dbf12901edacf14812a6fae25462920af42Steve Block    int base = currentInstruction[2].u.operand;
410692e5dbf12901edacf14812a6fae25462920af42Steve Block
411692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitLoad(base, regT1, regT0);
412692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitJumpSlowCaseIfNotJSCell(base, regT1);
413692e5dbf12901edacf14812a6fae25462920af42Steve Block    compileGetByIdHotPath();
414692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitStore(dst, regT1, regT0);
415e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_id), dst, regT1, regT0);
416692e5dbf12901edacf14812a6fae25462920af42Steve Block}
417692e5dbf12901edacf14812a6fae25462920af42Steve Block
418692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::compileGetByIdHotPath()
419692e5dbf12901edacf14812a6fae25462920af42Steve Block{
420692e5dbf12901edacf14812a6fae25462920af42Steve Block    // As for put_by_id, get_by_id requires the offset of the Structure and the offset of the access to be patched.
421692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump
422692e5dbf12901edacf14812a6fae25462920af42Steve Block    // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label
423692e5dbf12901edacf14812a6fae25462920af42Steve Block    // to jump back to if one of these trampolies finds a match.
424692e5dbf12901edacf14812a6fae25462920af42Steve Block
425692e5dbf12901edacf14812a6fae25462920af42Steve Block    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
426692e5dbf12901edacf14812a6fae25462920af42Steve Block
427692e5dbf12901edacf14812a6fae25462920af42Steve Block    Label hotPathBegin(this);
428692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
429692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessInstructionIndex++;
430692e5dbf12901edacf14812a6fae25462920af42Steve Block
431692e5dbf12901edacf14812a6fae25462920af42Steve Block    DataLabelPtr structureToCompare;
4322bde8e466a4451c7319e3a072d118917957d6554Steve Block    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
433692e5dbf12901edacf14812a6fae25462920af42Steve Block    addSlowCase(structureCheck);
43481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure);
43581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase);
436692e5dbf12901edacf14812a6fae25462920af42Steve Block
43781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT2);
438692e5dbf12901edacf14812a6fae25462920af42Steve Block    DataLabel32 displacementLabel1 = loadPtrWithAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT0); // payload
43981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel1), patchOffsetGetByIdPropertyMapOffset1);
440692e5dbf12901edacf14812a6fae25462920af42Steve Block    DataLabel32 displacementLabel2 = loadPtrWithAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT1); // tag
44181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel2), patchOffsetGetByIdPropertyMapOffset2);
442692e5dbf12901edacf14812a6fae25462920af42Steve Block
443692e5dbf12901edacf14812a6fae25462920af42Steve Block    Label putResult(this);
44481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, putResult), patchOffsetGetByIdPutResult);
445692e5dbf12901edacf14812a6fae25462920af42Steve Block
446692e5dbf12901edacf14812a6fae25462920af42Steve Block    END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
447692e5dbf12901edacf14812a6fae25462920af42Steve Block}
448692e5dbf12901edacf14812a6fae25462920af42Steve Block
449692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
450692e5dbf12901edacf14812a6fae25462920af42Steve Block{
451692e5dbf12901edacf14812a6fae25462920af42Steve Block    int dst = currentInstruction[1].u.operand;
452692e5dbf12901edacf14812a6fae25462920af42Steve Block    int base = currentInstruction[2].u.operand;
453692e5dbf12901edacf14812a6fae25462920af42Steve Block    int ident = currentInstruction[3].u.operand;
454692e5dbf12901edacf14812a6fae25462920af42Steve Block
455692e5dbf12901edacf14812a6fae25462920af42Steve Block    compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter);
456692e5dbf12901edacf14812a6fae25462920af42Steve Block}
457692e5dbf12901edacf14812a6fae25462920af42Steve Block
458692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck)
459692e5dbf12901edacf14812a6fae25462920af42Steve Block{
460692e5dbf12901edacf14812a6fae25462920af42Steve Block    // As for the hot path of get_by_id, above, we ensure that we can use an architecture specific offset
461692e5dbf12901edacf14812a6fae25462920af42Steve Block    // so that we only need track one pointer into the slow case code - we track a pointer to the location
462692e5dbf12901edacf14812a6fae25462920af42Steve Block    // of the call (which we can use to look up the patch information), but should a array-length or
463692e5dbf12901edacf14812a6fae25462920af42Steve Block    // prototype access trampoline fail we want to bail out back to here.  To do so we can subtract back
464692e5dbf12901edacf14812a6fae25462920af42Steve Block    // the distance from the call to the head of the slow case.
465692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCaseIfNotJSCell(iter, base);
466692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter);
467692e5dbf12901edacf14812a6fae25462920af42Steve Block
468692e5dbf12901edacf14812a6fae25462920af42Steve Block    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
469692e5dbf12901edacf14812a6fae25462920af42Steve Block
470692e5dbf12901edacf14812a6fae25462920af42Steve Block#ifndef NDEBUG
471692e5dbf12901edacf14812a6fae25462920af42Steve Block    Label coldPathBegin(this);
472692e5dbf12901edacf14812a6fae25462920af42Steve Block#endif
473692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id);
474692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(regT1, regT0);
4752bde8e466a4451c7319e3a072d118917957d6554Steve Block    stubCall.addArgument(TrustedImmPtr(ident));
476692e5dbf12901edacf14812a6fae25462920af42Steve Block    Call call = stubCall.call(dst);
477692e5dbf12901edacf14812a6fae25462920af42Steve Block
4782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    END_UNINTERRUPTED_SEQUENCE_FOR_PUT(sequenceGetByIdSlowCase, dst);
479692e5dbf12901edacf14812a6fae25462920af42Steve Block
48081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(coldPathBegin, call), patchOffsetGetByIdSlowCaseCall);
481692e5dbf12901edacf14812a6fae25462920af42Steve Block
482692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Track the location of the call; this will be used to recover patch information.
483692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call;
484692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessInstructionIndex++;
485692e5dbf12901edacf14812a6fae25462920af42Steve Block}
486692e5dbf12901edacf14812a6fae25462920af42Steve Block
487692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_put_by_id(Instruction* currentInstruction)
488692e5dbf12901edacf14812a6fae25462920af42Steve Block{
489692e5dbf12901edacf14812a6fae25462920af42Steve Block    // In order to be able to patch both the Structure, and the object offset, we store one pointer,
490692e5dbf12901edacf14812a6fae25462920af42Steve Block    // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code
491692e5dbf12901edacf14812a6fae25462920af42Steve Block    // such that the Structure & offset are always at the same distance from this.
492692e5dbf12901edacf14812a6fae25462920af42Steve Block
493692e5dbf12901edacf14812a6fae25462920af42Steve Block    int base = currentInstruction[1].u.operand;
494692e5dbf12901edacf14812a6fae25462920af42Steve Block    int value = currentInstruction[3].u.operand;
495692e5dbf12901edacf14812a6fae25462920af42Steve Block
496692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitLoad2(base, regT1, regT0, value, regT3, regT2);
497692e5dbf12901edacf14812a6fae25462920af42Steve Block
498692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitJumpSlowCaseIfNotJSCell(base, regT1);
499692e5dbf12901edacf14812a6fae25462920af42Steve Block
500692e5dbf12901edacf14812a6fae25462920af42Steve Block    BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById);
501692e5dbf12901edacf14812a6fae25462920af42Steve Block
502692e5dbf12901edacf14812a6fae25462920af42Steve Block    Label hotPathBegin(this);
503692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
504692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessInstructionIndex++;
505692e5dbf12901edacf14812a6fae25462920af42Steve Block
506692e5dbf12901edacf14812a6fae25462920af42Steve Block    // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over.
507692e5dbf12901edacf14812a6fae25462920af42Steve Block    DataLabelPtr structureToCompare;
5082bde8e466a4451c7319e3a072d118917957d6554Steve Block    addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
50981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure);
510692e5dbf12901edacf14812a6fae25462920af42Steve Block
51181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0);
512692e5dbf12901edacf14812a6fae25462920af42Steve Block    DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT0, patchGetByIdDefaultOffset)); // payload
513692e5dbf12901edacf14812a6fae25462920af42Steve Block    DataLabel32 displacementLabel2 = storePtrWithAddressOffsetPatch(regT3, Address(regT0, patchGetByIdDefaultOffset)); // tag
514692e5dbf12901edacf14812a6fae25462920af42Steve Block
515692e5dbf12901edacf14812a6fae25462920af42Steve Block    END_UNINTERRUPTED_SEQUENCE(sequencePutById);
516692e5dbf12901edacf14812a6fae25462920af42Steve Block
51781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel1), patchOffsetPutByIdPropertyMapOffset1);
51881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel2), patchOffsetPutByIdPropertyMapOffset2);
519692e5dbf12901edacf14812a6fae25462920af42Steve Block}
520692e5dbf12901edacf14812a6fae25462920af42Steve Block
521692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
522692e5dbf12901edacf14812a6fae25462920af42Steve Block{
523692e5dbf12901edacf14812a6fae25462920af42Steve Block    int base = currentInstruction[1].u.operand;
524692e5dbf12901edacf14812a6fae25462920af42Steve Block    int ident = currentInstruction[2].u.operand;
525e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    int direct = currentInstruction[8].u.operand;
526e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
527692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCaseIfNotJSCell(iter, base);
528692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter);
529692e5dbf12901edacf14812a6fae25462920af42Steve Block
530e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id);
531692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(regT1, regT0);
5322bde8e466a4451c7319e3a072d118917957d6554Steve Block    stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident))));
533692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(regT3, regT2);
534692e5dbf12901edacf14812a6fae25462920af42Steve Block    Call call = stubCall.call();
535692e5dbf12901edacf14812a6fae25462920af42Steve Block
536692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Track the location of the call; this will be used to recover patch information.
537692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call;
538692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_propertyAccessInstructionIndex++;
539692e5dbf12901edacf14812a6fae25462920af42Steve Block}
540692e5dbf12901edacf14812a6fae25462920af42Steve Block
541692e5dbf12901edacf14812a6fae25462920af42Steve Block// Compile a store into an object's property storage.  May overwrite base.
542692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, Structure* structure, size_t cachedOffset)
543692e5dbf12901edacf14812a6fae25462920af42Steve Block{
544692e5dbf12901edacf14812a6fae25462920af42Steve Block    int offset = cachedOffset;
545692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (structure->isUsingInlineStorage())
54681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        offset += JSObject::offsetOfInlineStorage() /  sizeof(Register);
547692e5dbf12901edacf14812a6fae25462920af42Steve Block    else
54881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
549692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitStore(offset, valueTag, valuePayload, base);
550692e5dbf12901edacf14812a6fae25462920af42Steve Block}
551692e5dbf12901edacf14812a6fae25462920af42Steve Block
552692e5dbf12901edacf14812a6fae25462920af42Steve Block// Compile a load from an object's property storage.  May overwrite base.
553692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset)
554692e5dbf12901edacf14812a6fae25462920af42Steve Block{
555692e5dbf12901edacf14812a6fae25462920af42Steve Block    int offset = cachedOffset;
55681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (structure->isUsingInlineStorage()) {
55781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        offset += JSObject::offsetOfInlineStorage() / sizeof(Register);
55881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        emitLoad(offset, resultTag, resultPayload, base);
55981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    } else {
56081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        RegisterID temp = resultPayload;
56181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), temp);
56281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        emitLoad(offset, resultTag, resultPayload, temp);
56381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
564692e5dbf12901edacf14812a6fae25462920af42Steve Block}
565692e5dbf12901edacf14812a6fae25462920af42Steve Block
56681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid JIT::compileGetDirectOffset(JSObject* base, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
567692e5dbf12901edacf14812a6fae25462920af42Steve Block{
56881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    load32(reinterpret_cast<char*>(&base->m_propertyStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload), resultPayload);
56981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    load32(reinterpret_cast<char*>(&base->m_propertyStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag), resultTag);
570692e5dbf12901edacf14812a6fae25462920af42Steve Block}
571692e5dbf12901edacf14812a6fae25462920af42Steve Block
572dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochvoid JIT::testPrototype(JSValue prototype, JumpList& failureCases)
573692e5dbf12901edacf14812a6fae25462920af42Steve Block{
574dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (prototype.isNull())
575692e5dbf12901edacf14812a6fae25462920af42Steve Block        return;
576692e5dbf12901edacf14812a6fae25462920af42Steve Block
577dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // We have a special case for X86_64 here because X86 instructions that take immediate values
578dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // only take 32 bit immediate values, wheras the pointer constants we are using here are 64 bit
579dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // values.  In the non X86_64 case, the generated code is slightly more efficient because it uses
580dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // two less instructions and doesn't require any scratch registers.
581dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#if CPU(X86_64)
5822bde8e466a4451c7319e3a072d118917957d6554Steve Block    move(TrustedImmPtr(prototype.asCell()->structure()), regT3);
5832bde8e466a4451c7319e3a072d118917957d6554Steve Block    failureCases.append(branchPtr(NotEqual, AbsoluteAddress(prototype.asCell()->addressOfStructure()), regT3));
584dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#else
5852bde8e466a4451c7319e3a072d118917957d6554Steve Block    failureCases.append(branchPtr(NotEqual, AbsoluteAddress(prototype.asCell()->addressOfStructure()), TrustedImmPtr(prototype.asCell()->structure())));
586dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#endif
587692e5dbf12901edacf14812a6fae25462920af42Steve Block}
588692e5dbf12901edacf14812a6fae25462920af42Steve Block
5895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
590692e5dbf12901edacf14812a6fae25462920af42Steve Block{
591692e5dbf12901edacf14812a6fae25462920af42Steve Block    // It is assumed that regT0 contains the basePayload and regT1 contains the baseTag.  The value can be found on the stack.
592692e5dbf12901edacf14812a6fae25462920af42Steve Block
593692e5dbf12901edacf14812a6fae25462920af42Steve Block    JumpList failureCases;
5942bde8e466a4451c7319e3a072d118917957d6554Steve Block    failureCases.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
5952bde8e466a4451c7319e3a072d118917957d6554Steve Block    failureCases.append(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(oldStructure)));
596dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    testPrototype(oldStructure->storedPrototype(), failureCases);
597692e5dbf12901edacf14812a6fae25462920af42Steve Block
598e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    if (!direct) {
599e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        // Verify that nothing in the prototype chain has a setter for this property.
6002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        for (WriteBarrier<Structure>* it = chain->head(); *it; ++it)
601dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            testPrototype((*it)->storedPrototype(), failureCases);
602e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    }
603e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
604692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Reallocate property storage if needed.
605692e5dbf12901edacf14812a6fae25462920af42Steve Block    Call callTarget;
606692e5dbf12901edacf14812a6fae25462920af42Steve Block    bool willNeedStorageRealloc = oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
607692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (willNeedStorageRealloc) {
608692e5dbf12901edacf14812a6fae25462920af42Steve Block        // This trampoline was called to like a JIT stub; before we can can call again we need to
609692e5dbf12901edacf14812a6fae25462920af42Steve Block        // remove the return address from the stack, to prevent the stack from becoming misaligned.
610692e5dbf12901edacf14812a6fae25462920af42Steve Block        preserveReturnAddressAfterCall(regT3);
611692e5dbf12901edacf14812a6fae25462920af42Steve Block
612692e5dbf12901edacf14812a6fae25462920af42Steve Block        JITStubCall stubCall(this, cti_op_put_by_id_transition_realloc);
613692e5dbf12901edacf14812a6fae25462920af42Steve Block        stubCall.skipArgument(); // base
614692e5dbf12901edacf14812a6fae25462920af42Steve Block        stubCall.skipArgument(); // ident
615692e5dbf12901edacf14812a6fae25462920af42Steve Block        stubCall.skipArgument(); // value
6162bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImm32(oldStructure->propertyStorageCapacity()));
6172bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImm32(newStructure->propertyStorageCapacity()));
618692e5dbf12901edacf14812a6fae25462920af42Steve Block        stubCall.call(regT0);
619692e5dbf12901edacf14812a6fae25462920af42Steve Block
620692e5dbf12901edacf14812a6fae25462920af42Steve Block        restoreReturnAddressBeforeReturn(regT3);
621692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
6222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    storePtrWithWriteBarrier(TrustedImmPtr(newStructure), regT0, Address(regT0, JSCell::structureOffset()));
624692e5dbf12901edacf14812a6fae25462920af42Steve Block
6252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if CPU(MIPS) || CPU(SH4)
6265abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    // For MIPS, we don't add sizeof(void*) to the stack offset.
6275abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT3);
6285abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT2);
6295abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick#else
63006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + sizeof(void*) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT3);
63106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + sizeof(void*) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT2);
6325abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick#endif
633692e5dbf12901edacf14812a6fae25462920af42Steve Block
634692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Write the value
635692e5dbf12901edacf14812a6fae25462920af42Steve Block    compilePutDirectOffset(regT0, regT2, regT3, newStructure, cachedOffset);
636692e5dbf12901edacf14812a6fae25462920af42Steve Block
637692e5dbf12901edacf14812a6fae25462920af42Steve Block    ret();
638692e5dbf12901edacf14812a6fae25462920af42Steve Block
639692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT(!failureCases.empty());
640692e5dbf12901edacf14812a6fae25462920af42Steve Block    failureCases.link(this);
641692e5dbf12901edacf14812a6fae25462920af42Steve Block    restoreArgumentReferenceForTrampoline();
642692e5dbf12901edacf14812a6fae25462920af42Steve Block    Call failureCall = tailRecursiveCall();
643692e5dbf12901edacf14812a6fae25462920af42Steve Block
644dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
6455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
646e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    patchBuffer.link(failureCall, FunctionPtr(direct ? cti_op_put_by_id_direct_fail : cti_op_put_by_id_fail));
647692e5dbf12901edacf14812a6fae25462920af42Steve Block
648692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (willNeedStorageRealloc) {
649692e5dbf12901edacf14812a6fae25462920af42Steve Block        ASSERT(m_calls.size() == 1);
650692e5dbf12901edacf14812a6fae25462920af42Steve Block        patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
651692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
652692e5dbf12901edacf14812a6fae25462920af42Steve Block
653692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
6545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    stubInfo->stubRoutine = entryLabel;
655692e5dbf12901edacf14812a6fae25462920af42Steve Block    RepatchBuffer repatchBuffer(m_codeBlock);
656692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relinkCallerToTrampoline(returnAddress, entryLabel);
657692e5dbf12901edacf14812a6fae25462920af42Steve Block}
658692e5dbf12901edacf14812a6fae25462920af42Steve Block
659692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
660692e5dbf12901edacf14812a6fae25462920af42Steve Block{
661692e5dbf12901edacf14812a6fae25462920af42Steve Block    RepatchBuffer repatchBuffer(codeBlock);
662692e5dbf12901edacf14812a6fae25462920af42Steve Block
663692e5dbf12901edacf14812a6fae25462920af42Steve Block    // We don't want to patch more than once - in future go to cti_op_get_by_id_generic.
664692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Should probably go to JITStubs::cti_op_get_by_id_fail, but that doesn't do anything interesting right now.
665692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
666692e5dbf12901edacf14812a6fae25462920af42Steve Block
667692e5dbf12901edacf14812a6fae25462920af42Steve Block    int offset = sizeof(JSValue) * cachedOffset;
66881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
669692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
670692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), structure);
67106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
67206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag
673692e5dbf12901edacf14812a6fae25462920af42Steve Block}
674692e5dbf12901edacf14812a6fae25462920af42Steve Block
6752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid JIT::patchMethodCallProto(JSGlobalData& globalData, CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress)
676692e5dbf12901edacf14812a6fae25462920af42Steve Block{
677692e5dbf12901edacf14812a6fae25462920af42Steve Block    RepatchBuffer repatchBuffer(codeBlock);
678692e5dbf12901edacf14812a6fae25462920af42Steve Block
679692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT(!methodCallLinkInfo.cachedStructure);
6802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    methodCallLinkInfo.cachedStructure.set(globalData, codeBlock->ownerExecutable(), structure);
681692e5dbf12901edacf14812a6fae25462920af42Steve Block    Structure* prototypeStructure = proto->structure();
6822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    methodCallLinkInfo.cachedPrototypeStructure.set(globalData, codeBlock->ownerExecutable(), prototypeStructure);
683692e5dbf12901edacf14812a6fae25462920af42Steve Block
684692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.repatch(methodCallLinkInfo.structureLabel, structure);
685692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), proto);
686692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), prototypeStructure);
687692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), callee);
688692e5dbf12901edacf14812a6fae25462920af42Steve Block
689692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id));
690692e5dbf12901edacf14812a6fae25462920af42Steve Block}
691692e5dbf12901edacf14812a6fae25462920af42Steve Block
692e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkevoid JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct)
693692e5dbf12901edacf14812a6fae25462920af42Steve Block{
694692e5dbf12901edacf14812a6fae25462920af42Steve Block    RepatchBuffer repatchBuffer(codeBlock);
695692e5dbf12901edacf14812a6fae25462920af42Steve Block
696692e5dbf12901edacf14812a6fae25462920af42Steve Block    // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
697692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Should probably go to cti_op_put_by_id_fail, but that doesn't do anything interesting right now.
698e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
699692e5dbf12901edacf14812a6fae25462920af42Steve Block
700692e5dbf12901edacf14812a6fae25462920af42Steve Block    int offset = sizeof(JSValue) * cachedOffset;
70181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
702692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
703692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), structure);
70406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
70506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag
706692e5dbf12901edacf14812a6fae25462920af42Steve Block}
707692e5dbf12901edacf14812a6fae25462920af42Steve Block
7085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
709692e5dbf12901edacf14812a6fae25462920af42Steve Block{
7105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress);
7115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
712692e5dbf12901edacf14812a6fae25462920af42Steve Block    // regT0 holds a JSCell*
713692e5dbf12901edacf14812a6fae25462920af42Steve Block
714692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Check for array
7152bde8e466a4451c7319e3a072d118917957d6554Steve Block    Jump failureCases1 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr));
716692e5dbf12901edacf14812a6fae25462920af42Steve Block
717692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Checks out okay! - get the length from the storage
7182bde8e466a4451c7319e3a072d118917957d6554Steve Block    loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
719dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    load32(Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length)), regT2);
720692e5dbf12901edacf14812a6fae25462920af42Steve Block
7212bde8e466a4451c7319e3a072d118917957d6554Steve Block    Jump failureCases2 = branch32(Above, regT2, TrustedImm32(INT_MAX));
722692e5dbf12901edacf14812a6fae25462920af42Steve Block    move(regT2, regT0);
7232bde8e466a4451c7319e3a072d118917957d6554Steve Block    move(TrustedImm32(JSValue::Int32Tag), regT1);
724692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump success = jump();
725692e5dbf12901edacf14812a6fae25462920af42Steve Block
726dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
7275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
728692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Use the patch information to link the failure cases back to the original slow case routine.
729692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
730692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(failureCases1, slowCaseBegin);
731692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(failureCases2, slowCaseBegin);
732692e5dbf12901edacf14812a6fae25462920af42Steve Block
733692e5dbf12901edacf14812a6fae25462920af42Steve Block    // On success return back to the hot patch code, at a point it will perform the store to dest for us.
734692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
735692e5dbf12901edacf14812a6fae25462920af42Steve Block
736692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Track the stub we have created so that it will be deleted later.
737692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
7385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    stubInfo->stubRoutine = entryLabel;
7395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
740692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Finally patch the jump to slow case back in the hot path to jump here instead.
741692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
742692e5dbf12901edacf14812a6fae25462920af42Steve Block    RepatchBuffer repatchBuffer(m_codeBlock);
743692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relink(jumpLocation, entryLabel);
744692e5dbf12901edacf14812a6fae25462920af42Steve Block
745692e5dbf12901edacf14812a6fae25462920af42Steve Block    // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
746692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_array_fail));
747692e5dbf12901edacf14812a6fae25462920af42Steve Block}
748692e5dbf12901edacf14812a6fae25462920af42Steve Block
7495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
750692e5dbf12901edacf14812a6fae25462920af42Steve Block{
751692e5dbf12901edacf14812a6fae25462920af42Steve Block    // regT0 holds a JSCell*
752692e5dbf12901edacf14812a6fae25462920af42Steve Block
753692e5dbf12901edacf14812a6fae25462920af42Steve Block    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
754692e5dbf12901edacf14812a6fae25462920af42Steve Block    // referencing the prototype object - let's speculatively load it's table nice and early!)
755692e5dbf12901edacf14812a6fae25462920af42Steve Block    JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
756692e5dbf12901edacf14812a6fae25462920af42Steve Block
757692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump failureCases1 = checkStructure(regT0, structure);
758692e5dbf12901edacf14812a6fae25462920af42Steve Block
759692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Check the prototype object's Structure had not changed.
7602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const void* prototypeStructureAddress = protoObject->addressOfStructure();
761692e5dbf12901edacf14812a6fae25462920af42Steve Block#if CPU(X86_64)
7622bde8e466a4451c7319e3a072d118917957d6554Steve Block    move(TrustedImmPtr(prototypeStructure), regT3);
763692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
764692e5dbf12901edacf14812a6fae25462920af42Steve Block#else
7652bde8e466a4451c7319e3a072d118917957d6554Steve Block    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), TrustedImmPtr(prototypeStructure));
766692e5dbf12901edacf14812a6fae25462920af42Steve Block#endif
767dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    bool needsStubLink = false;
768dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // Checks out okay!
769dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (slot.cachedPropertyType() == PropertySlot::Getter) {
770dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        needsStubLink = true;
77181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
772dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
773dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.addArgument(regT1);
774dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.addArgument(regT0);
7752bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
776dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.call();
777dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
778dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        needsStubLink = true;
779dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
7802bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(protoObject));
7812bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
7822bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
7832bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
784dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.call();
785dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else
78681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
787692e5dbf12901edacf14812a6fae25462920af42Steve Block
788692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump success = jump();
789692e5dbf12901edacf14812a6fae25462920af42Steve Block
790dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
7915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
792692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Use the patch information to link the failure cases back to the original slow case routine.
793692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
794692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(failureCases1, slowCaseBegin);
795692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(failureCases2, slowCaseBegin);
796692e5dbf12901edacf14812a6fae25462920af42Steve Block
797692e5dbf12901edacf14812a6fae25462920af42Steve Block    // On success return back to the hot patch code, at a point it will perform the store to dest for us.
798692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
799dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
800dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (needsStubLink) {
801dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
802dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (iter->to)
803dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                patchBuffer.link(iter->from, FunctionPtr(iter->to));
804dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
805dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
806dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
807692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Track the stub we have created so that it will be deleted later.
808692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
8095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    stubInfo->stubRoutine = entryLabel;
810692e5dbf12901edacf14812a6fae25462920af42Steve Block
811692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Finally patch the jump to slow case back in the hot path to jump here instead.
812692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
813692e5dbf12901edacf14812a6fae25462920af42Steve Block    RepatchBuffer repatchBuffer(m_codeBlock);
814692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relink(jumpLocation, entryLabel);
815692e5dbf12901edacf14812a6fae25462920af42Steve Block
816692e5dbf12901edacf14812a6fae25462920af42Steve Block    // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
817692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
818692e5dbf12901edacf14812a6fae25462920af42Steve Block}
819692e5dbf12901edacf14812a6fae25462920af42Steve Block
820692e5dbf12901edacf14812a6fae25462920af42Steve Block
8215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
822692e5dbf12901edacf14812a6fae25462920af42Steve Block{
823692e5dbf12901edacf14812a6fae25462920af42Steve Block    // regT0 holds a JSCell*
824692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump failureCase = checkStructure(regT0, structure);
825dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    bool needsStubLink = false;
826dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (slot.cachedPropertyType() == PropertySlot::Getter) {
827dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        needsStubLink = true;
82881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        compileGetDirectOffset(regT0, regT2, regT1, structure, cachedOffset);
829dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
830dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.addArgument(regT1);
831dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.addArgument(regT0);
8322bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
833dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.call();
834dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
835dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        needsStubLink = true;
836dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
837dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.addArgument(regT0);
8382bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
8392bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
8402bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
841dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.call();
842dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else
843dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        compileGetDirectOffset(regT0, regT1, regT0, structure, cachedOffset);
844dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
845692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump success = jump();
846692e5dbf12901edacf14812a6fae25462920af42Steve Block
847dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
848dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (needsStubLink) {
849dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
850dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (iter->to)
851dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                patchBuffer.link(iter->from, FunctionPtr(iter->to));
852dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
853dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
854692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Use the patch information to link the failure cases back to the original slow case routine.
855692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine;
856692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (!lastProtoBegin)
857692e5dbf12901edacf14812a6fae25462920af42Steve Block        lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
858692e5dbf12901edacf14812a6fae25462920af42Steve Block
859692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(failureCase, lastProtoBegin);
860692e5dbf12901edacf14812a6fae25462920af42Steve Block
861692e5dbf12901edacf14812a6fae25462920af42Steve Block    // On success return back to the hot patch code, at a point it will perform the store to dest for us.
862692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
863dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
864692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
8652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), entryLabel, structure);
867692e5dbf12901edacf14812a6fae25462920af42Steve Block
868692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Finally patch the jump to slow case back in the hot path to jump here instead.
869692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
870692e5dbf12901edacf14812a6fae25462920af42Steve Block    RepatchBuffer repatchBuffer(m_codeBlock);
871692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relink(jumpLocation, entryLabel);
872692e5dbf12901edacf14812a6fae25462920af42Steve Block}
873692e5dbf12901edacf14812a6fae25462920af42Steve Block
8745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
875692e5dbf12901edacf14812a6fae25462920af42Steve Block{
876692e5dbf12901edacf14812a6fae25462920af42Steve Block    // regT0 holds a JSCell*
877692e5dbf12901edacf14812a6fae25462920af42Steve Block
878692e5dbf12901edacf14812a6fae25462920af42Steve Block    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
879692e5dbf12901edacf14812a6fae25462920af42Steve Block    // referencing the prototype object - let's speculatively load it's table nice and early!)
880692e5dbf12901edacf14812a6fae25462920af42Steve Block    JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
881692e5dbf12901edacf14812a6fae25462920af42Steve Block
882692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Check eax is an object of the right Structure.
883692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump failureCases1 = checkStructure(regT0, structure);
884692e5dbf12901edacf14812a6fae25462920af42Steve Block
885692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Check the prototype object's Structure had not changed.
8862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const void* prototypeStructureAddress = protoObject->addressOfStructure();
887692e5dbf12901edacf14812a6fae25462920af42Steve Block#if CPU(X86_64)
8882bde8e466a4451c7319e3a072d118917957d6554Steve Block    move(TrustedImmPtr(prototypeStructure), regT3);
889692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
890692e5dbf12901edacf14812a6fae25462920af42Steve Block#else
8912bde8e466a4451c7319e3a072d118917957d6554Steve Block    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), TrustedImmPtr(prototypeStructure));
892692e5dbf12901edacf14812a6fae25462920af42Steve Block#endif
893692e5dbf12901edacf14812a6fae25462920af42Steve Block
894dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    bool needsStubLink = false;
895dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (slot.cachedPropertyType() == PropertySlot::Getter) {
896dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        needsStubLink = true;
89781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
898dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
899dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.addArgument(regT1);
900dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.addArgument(regT0);
9012bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
902dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.call();
903dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
904dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        needsStubLink = true;
905dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
9062bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(protoObject));
9072bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
9082bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
9092bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
910dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.call();
911dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else
91281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
913692e5dbf12901edacf14812a6fae25462920af42Steve Block
914692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump success = jump();
915692e5dbf12901edacf14812a6fae25462920af42Steve Block
916dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
917dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (needsStubLink) {
918dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
919dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (iter->to)
920dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                patchBuffer.link(iter->from, FunctionPtr(iter->to));
921dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
922dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
923692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Use the patch information to link the failure cases back to the original slow case routine.
924692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
925692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(failureCases1, lastProtoBegin);
926692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(failureCases2, lastProtoBegin);
927692e5dbf12901edacf14812a6fae25462920af42Steve Block
928692e5dbf12901edacf14812a6fae25462920af42Steve Block    // On success return back to the hot patch code, at a point it will perform the store to dest for us.
929692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
930692e5dbf12901edacf14812a6fae25462920af42Steve Block
931692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
9322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, prototypeStructure);
934692e5dbf12901edacf14812a6fae25462920af42Steve Block
935692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Finally patch the jump to slow case back in the hot path to jump here instead.
936692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
937692e5dbf12901edacf14812a6fae25462920af42Steve Block    RepatchBuffer repatchBuffer(m_codeBlock);
938692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relink(jumpLocation, entryLabel);
939692e5dbf12901edacf14812a6fae25462920af42Steve Block}
940692e5dbf12901edacf14812a6fae25462920af42Steve Block
9415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
942692e5dbf12901edacf14812a6fae25462920af42Steve Block{
943692e5dbf12901edacf14812a6fae25462920af42Steve Block    // regT0 holds a JSCell*
944692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT(count);
945692e5dbf12901edacf14812a6fae25462920af42Steve Block
946692e5dbf12901edacf14812a6fae25462920af42Steve Block    JumpList bucketsOfFail;
947692e5dbf12901edacf14812a6fae25462920af42Steve Block
948692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Check eax is an object of the right Structure.
949692e5dbf12901edacf14812a6fae25462920af42Steve Block    bucketsOfFail.append(checkStructure(regT0, structure));
950692e5dbf12901edacf14812a6fae25462920af42Steve Block
951692e5dbf12901edacf14812a6fae25462920af42Steve Block    Structure* currStructure = structure;
9522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    WriteBarrier<Structure>* it = chain->head();
953692e5dbf12901edacf14812a6fae25462920af42Steve Block    JSObject* protoObject = 0;
954dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    for (unsigned i = 0; i < count; ++i, ++it) {
955692e5dbf12901edacf14812a6fae25462920af42Steve Block        protoObject = asObject(currStructure->prototypeForLookup(callFrame));
956dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        currStructure = it->get();
957dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        testPrototype(protoObject, bucketsOfFail);
958692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
959692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT(protoObject);
960692e5dbf12901edacf14812a6fae25462920af42Steve Block
961dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    bool needsStubLink = false;
962dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (slot.cachedPropertyType() == PropertySlot::Getter) {
963dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        needsStubLink = true;
96481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
965dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
966dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.addArgument(regT1);
967dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.addArgument(regT0);
9682bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
969dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.call();
970dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
971dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        needsStubLink = true;
972dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
9732bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(protoObject));
9742bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
9752bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
9762bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
977dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.call();
978dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else
97981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
980dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
981692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump success = jump();
982692e5dbf12901edacf14812a6fae25462920af42Steve Block
983dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
984dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (needsStubLink) {
985dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
986dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (iter->to)
987dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                patchBuffer.link(iter->from, FunctionPtr(iter->to));
988dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
989dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
990692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Use the patch information to link the failure cases back to the original slow case routine.
991692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
992692e5dbf12901edacf14812a6fae25462920af42Steve Block
993692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(bucketsOfFail, lastProtoBegin);
994692e5dbf12901edacf14812a6fae25462920af42Steve Block
995692e5dbf12901edacf14812a6fae25462920af42Steve Block    // On success return back to the hot patch code, at a point it will perform the store to dest for us.
996692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
997692e5dbf12901edacf14812a6fae25462920af42Steve Block
998692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
999692e5dbf12901edacf14812a6fae25462920af42Steve Block
1000692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Track the stub we have created so that it will be deleted later.
10012bde8e466a4451c7319e3a072d118917957d6554Steve Block    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, chain);
1002692e5dbf12901edacf14812a6fae25462920af42Steve Block
1003692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Finally patch the jump to slow case back in the hot path to jump here instead.
1004692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
1005692e5dbf12901edacf14812a6fae25462920af42Steve Block    RepatchBuffer repatchBuffer(m_codeBlock);
1006692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relink(jumpLocation, entryLabel);
1007692e5dbf12901edacf14812a6fae25462920af42Steve Block}
1008692e5dbf12901edacf14812a6fae25462920af42Steve Block
10095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
1010692e5dbf12901edacf14812a6fae25462920af42Steve Block{
1011692e5dbf12901edacf14812a6fae25462920af42Steve Block    // regT0 holds a JSCell*
1012692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT(count);
1013692e5dbf12901edacf14812a6fae25462920af42Steve Block
1014692e5dbf12901edacf14812a6fae25462920af42Steve Block    JumpList bucketsOfFail;
1015692e5dbf12901edacf14812a6fae25462920af42Steve Block
1016692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Check eax is an object of the right Structure.
1017692e5dbf12901edacf14812a6fae25462920af42Steve Block    bucketsOfFail.append(checkStructure(regT0, structure));
1018692e5dbf12901edacf14812a6fae25462920af42Steve Block
1019692e5dbf12901edacf14812a6fae25462920af42Steve Block    Structure* currStructure = structure;
10202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    WriteBarrier<Structure>* it = chain->head();
1021692e5dbf12901edacf14812a6fae25462920af42Steve Block    JSObject* protoObject = 0;
1022dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    for (unsigned i = 0; i < count; ++i, ++it) {
1023692e5dbf12901edacf14812a6fae25462920af42Steve Block        protoObject = asObject(currStructure->prototypeForLookup(callFrame));
1024dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        currStructure = it->get();
1025dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        testPrototype(protoObject, bucketsOfFail);
1026692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
1027692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT(protoObject);
1028692e5dbf12901edacf14812a6fae25462920af42Steve Block
1029dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    bool needsStubLink = false;
1030dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (slot.cachedPropertyType() == PropertySlot::Getter) {
1031dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        needsStubLink = true;
103281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
1033dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
1034dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.addArgument(regT1);
1035dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.addArgument(regT0);
10362bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
1037dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.call();
1038dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
1039dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        needsStubLink = true;
1040dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
10412bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(protoObject));
10422bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
10432bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
10442bde8e466a4451c7319e3a072d118917957d6554Steve Block        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
1045dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stubCall.call();
1046dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else
104781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
1048692e5dbf12901edacf14812a6fae25462920af42Steve Block    Jump success = jump();
1049692e5dbf12901edacf14812a6fae25462920af42Steve Block
1050dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
1051dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (needsStubLink) {
1052dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
1053dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (iter->to)
1054dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                patchBuffer.link(iter->from, FunctionPtr(iter->to));
1055dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1056dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1057692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Use the patch information to link the failure cases back to the original slow case routine.
1058692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall));
1059692e5dbf12901edacf14812a6fae25462920af42Steve Block
1060692e5dbf12901edacf14812a6fae25462920af42Steve Block    // On success return back to the hot patch code, at a point it will perform the store to dest for us.
1061692e5dbf12901edacf14812a6fae25462920af42Steve Block    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
1062692e5dbf12901edacf14812a6fae25462920af42Steve Block
1063692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Track the stub we have created so that it will be deleted later.
1064692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
10655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    stubInfo->stubRoutine = entryLabel;
10665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1067692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Finally patch the jump to slow case back in the hot path to jump here instead.
1068692e5dbf12901edacf14812a6fae25462920af42Steve Block    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
1069692e5dbf12901edacf14812a6fae25462920af42Steve Block    RepatchBuffer repatchBuffer(m_codeBlock);
1070692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relink(jumpLocation, entryLabel);
1071692e5dbf12901edacf14812a6fae25462920af42Steve Block
1072692e5dbf12901edacf14812a6fae25462920af42Steve Block    // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
1073692e5dbf12901edacf14812a6fae25462920af42Steve Block    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
1074692e5dbf12901edacf14812a6fae25462920af42Steve Block}
1075692e5dbf12901edacf14812a6fae25462920af42Steve Block
1076692e5dbf12901edacf14812a6fae25462920af42Steve Block/* ------------------------------ END: !ENABLE / ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
1077692e5dbf12901edacf14812a6fae25462920af42Steve Block
1078692e5dbf12901edacf14812a6fae25462920af42Steve Block#endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1079692e5dbf12901edacf14812a6fae25462920af42Steve Block
108081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID offset)
1081692e5dbf12901edacf14812a6fae25462920af42Steve Block{
1082692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT(sizeof(JSValue) == 8);
1083692e5dbf12901edacf14812a6fae25462920af42Steve Block
108481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
1085692e5dbf12901edacf14812a6fae25462920af42Steve Block    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
1086692e5dbf12901edacf14812a6fae25462920af42Steve Block    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
1087692e5dbf12901edacf14812a6fae25462920af42Steve Block}
1088692e5dbf12901edacf14812a6fae25462920af42Steve Block
1089692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emit_op_get_by_pname(Instruction* currentInstruction)
1090692e5dbf12901edacf14812a6fae25462920af42Steve Block{
1091692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned dst = currentInstruction[1].u.operand;
1092692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[2].u.operand;
1093692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[3].u.operand;
1094692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned expected = currentInstruction[4].u.operand;
1095692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned iter = currentInstruction[5].u.operand;
1096692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned i = currentInstruction[6].u.operand;
1097692e5dbf12901edacf14812a6fae25462920af42Steve Block
1098692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitLoad2(property, regT1, regT0, base, regT3, regT2);
1099692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitJumpSlowCaseIfNotJSCell(property, regT1);
1100692e5dbf12901edacf14812a6fae25462920af42Steve Block    addSlowCase(branchPtr(NotEqual, regT0, payloadFor(expected)));
1101692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Property registers are now available as the property is known
1102692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitJumpSlowCaseIfNotJSCell(base, regT3);
1103692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitLoadPayload(iter, regT1);
1104692e5dbf12901edacf14812a6fae25462920af42Steve Block
1105692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Test base's structure
11062bde8e466a4451c7319e3a072d118917957d6554Steve Block    loadPtr(Address(regT2, JSCell::structureOffset()), regT0);
1107692e5dbf12901edacf14812a6fae25462920af42Steve Block    addSlowCase(branchPtr(NotEqual, regT0, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure))));
1108692e5dbf12901edacf14812a6fae25462920af42Steve Block    load32(addressFor(i), regT3);
11092bde8e466a4451c7319e3a072d118917957d6554Steve Block    sub32(TrustedImm32(1), regT3);
1110692e5dbf12901edacf14812a6fae25462920af42Steve Block    addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots))));
111181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    compileGetDirectOffset(regT2, regT1, regT0, regT3);
1112692e5dbf12901edacf14812a6fae25462920af42Steve Block
1113692e5dbf12901edacf14812a6fae25462920af42Steve Block    emitStore(dst, regT1, regT0);
1114e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_pname), dst, regT1, regT0);
1115692e5dbf12901edacf14812a6fae25462920af42Steve Block}
1116692e5dbf12901edacf14812a6fae25462920af42Steve Block
1117692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1118692e5dbf12901edacf14812a6fae25462920af42Steve Block{
1119692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned dst = currentInstruction[1].u.operand;
1120692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned base = currentInstruction[2].u.operand;
1121692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned property = currentInstruction[3].u.operand;
1122692e5dbf12901edacf14812a6fae25462920af42Steve Block
1123692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCaseIfNotJSCell(iter, property);
1124692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter);
1125692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCaseIfNotJSCell(iter, base);
1126692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter);
1127692e5dbf12901edacf14812a6fae25462920af42Steve Block    linkSlowCase(iter);
1128692e5dbf12901edacf14812a6fae25462920af42Steve Block
1129692e5dbf12901edacf14812a6fae25462920af42Steve Block    JITStubCall stubCall(this, cti_op_get_by_val);
1130692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(base);
1131692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.addArgument(property);
1132692e5dbf12901edacf14812a6fae25462920af42Steve Block    stubCall.call(dst);
1133692e5dbf12901edacf14812a6fae25462920af42Steve Block}
1134692e5dbf12901edacf14812a6fae25462920af42Steve Block
1135692e5dbf12901edacf14812a6fae25462920af42Steve Block} // namespace JSC
1136692e5dbf12901edacf14812a6fae25462920af42Steve Block
1137e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#endif // USE(JSVALUE32_64)
1138692e5dbf12901edacf14812a6fae25462920af42Steve Block#endif // ENABLE(JIT)
1139