We should be able to inline getter/setter calls inside an inline cache even when...
[WebKit-https.git] / Source / JavaScriptCore / jit / JITPropertyAccess32_64.cpp
1 /*
2  * Copyright (C) 2008, 2009, 2014, 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #if ENABLE(JIT)
29 #if USE(JSVALUE32_64)
30 #include "JIT.h"
31
32 #include "CodeBlock.h"
33 #include "DirectArguments.h"
34 #include "GCAwareJITStubRoutine.h"
35 #include "Interpreter.h"
36 #include "JITInlines.h"
37 #include "JSArray.h"
38 #include "JSEnvironmentRecord.h"
39 #include "JSFunction.h"
40 #include "LinkBuffer.h"
41 #include "ResultType.h"
42 #include "SamplingTool.h"
43 #include "SlowPathCall.h"
44 #include <wtf/StringPrintStream.h>
45
46
47 namespace JSC {
48     
49 void JIT::emit_op_put_by_index(Instruction* currentInstruction)
50 {
51     int base = currentInstruction[1].u.operand;
52     int property = currentInstruction[2].u.operand;
53     int value = currentInstruction[3].u.operand;
54
55     emitLoad(base, regT1, regT0);
56     emitLoad(value, regT3, regT2);
57     callOperation(operationPutByIndex, regT1, regT0, property, regT3, regT2);
58 }
59
60 void JIT::emit_op_put_getter_by_id(Instruction* currentInstruction)
61 {
62     int base = currentInstruction[1].u.operand;
63     int property = currentInstruction[2].u.operand;
64     int options = currentInstruction[3].u.operand;
65     int getter = currentInstruction[4].u.operand;
66
67     emitLoadPayload(base, regT1);
68     emitLoadPayload(getter, regT3);
69     callOperation(operationPutGetterById, regT1, &m_codeBlock->identifier(property), options, regT3);
70 }
71
72 void JIT::emit_op_put_setter_by_id(Instruction* currentInstruction)
73 {
74     int base = currentInstruction[1].u.operand;
75     int property = currentInstruction[2].u.operand;
76     unsigned options = currentInstruction[3].u.operand;
77     int setter = currentInstruction[4].u.operand;
78
79     emitLoadPayload(base, regT1);
80     emitLoadPayload(setter, regT3);
81     callOperation(operationPutSetterById, regT1, &m_codeBlock->identifier(property), options, regT3);
82 }
83
84 void JIT::emit_op_put_getter_setter(Instruction* currentInstruction)
85 {
86     int base = currentInstruction[1].u.operand;
87     int property = currentInstruction[2].u.operand;
88     unsigned attribute = currentInstruction[3].u.operand;
89     int getter = currentInstruction[4].u.operand;
90     int setter = currentInstruction[5].u.operand;
91
92     emitLoadPayload(base, regT1);
93     emitLoadPayload(getter, regT3);
94     emitLoadPayload(setter, regT4);
95     callOperation(operationPutGetterSetter, regT1, &m_codeBlock->identifier(property), attribute, regT3, regT4);
96 }
97
98 void JIT::emit_op_put_getter_by_val(Instruction* currentInstruction)
99 {
100     int base = currentInstruction[1].u.operand;
101     int property = currentInstruction[2].u.operand;
102     int32_t attributes = currentInstruction[3].u.operand;
103     int getter = currentInstruction[4].u.operand;
104
105     emitLoadPayload(base, regT2);
106     emitLoad(property, regT1, regT0);
107     emitLoadPayload(getter, regT3);
108     callOperation(operationPutGetterByVal, regT2, regT1, regT0, attributes, regT3);
109 }
110
111 void JIT::emit_op_put_setter_by_val(Instruction* currentInstruction)
112 {
113     int base = currentInstruction[1].u.operand;
114     int property = currentInstruction[2].u.operand;
115     int32_t attributes = currentInstruction[3].u.operand;
116     int getter = currentInstruction[4].u.operand;
117
118     emitLoadPayload(base, regT2);
119     emitLoad(property, regT1, regT0);
120     emitLoadPayload(getter, regT3);
121     callOperation(operationPutSetterByVal, regT2, regT1, regT0, attributes, regT3);
122 }
123
124 void JIT::emit_op_del_by_id(Instruction* currentInstruction)
125 {
126     int dst = currentInstruction[1].u.operand;
127     int base = currentInstruction[2].u.operand;
128     int property = currentInstruction[3].u.operand;
129     emitLoad(base, regT1, regT0);
130     callOperation(operationDeleteById, dst, regT1, regT0, &m_codeBlock->identifier(property));
131 }
132
133 JIT::CodeRef JIT::stringGetByValStubGenerator(VM* vm)
134 {
135     JSInterfaceJIT jit(vm);
136     JumpList failures;
137     failures.append(jit.branchStructure(NotEqual, Address(regT0, JSCell::structureIDOffset()), vm->stringStructure.get()));
138     
139     // Load string length to regT1, and start the process of loading the data pointer into regT0
140     jit.load32(Address(regT0, ThunkHelpers::jsStringLengthOffset()), regT1);
141     jit.loadPtr(Address(regT0, ThunkHelpers::jsStringValueOffset()), regT0);
142     failures.append(jit.branchTest32(Zero, regT0));
143     
144     // Do an unsigned compare to simultaneously filter negative indices as well as indices that are too large
145     failures.append(jit.branch32(AboveOrEqual, regT2, regT1));
146     
147     // Load the character
148     JumpList is16Bit;
149     JumpList cont8Bit;
150     // Load the string flags
151     jit.loadPtr(Address(regT0, StringImpl::flagsOffset()), regT1);
152     jit.loadPtr(Address(regT0, StringImpl::dataOffset()), regT0);
153     is16Bit.append(jit.branchTest32(Zero, regT1, TrustedImm32(StringImpl::flagIs8Bit())));
154     jit.load8(BaseIndex(regT0, regT2, TimesOne, 0), regT0);
155     cont8Bit.append(jit.jump());
156     is16Bit.link(&jit);
157     jit.load16(BaseIndex(regT0, regT2, TimesTwo, 0), regT0);
158
159     cont8Bit.link(&jit);
160     
161     failures.append(jit.branch32(AboveOrEqual, regT0, TrustedImm32(0x100)));
162     jit.move(TrustedImmPtr(vm->smallStrings.singleCharacterStrings()), regT1);
163     jit.loadPtr(BaseIndex(regT1, regT0, ScalePtr, 0), regT0);
164     jit.move(TrustedImm32(JSValue::CellTag), regT1); // We null check regT0 on return so this is safe
165     jit.ret();
166
167     failures.link(&jit);
168     jit.move(TrustedImm32(0), regT0);
169     jit.ret();
170     
171     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
172     return FINALIZE_CODE(patchBuffer, ("String get_by_val stub"));
173 }
174
175 void JIT::emit_op_get_by_val(Instruction* currentInstruction)
176 {
177     int dst = currentInstruction[1].u.operand;
178     int base = currentInstruction[2].u.operand;
179     int property = currentInstruction[3].u.operand;
180     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
181     ByValInfo* byValInfo = m_codeBlock->addByValInfo();
182     
183     emitLoad2(base, regT1, regT0, property, regT3, regT2);
184     
185     emitJumpSlowCaseIfNotJSCell(base, regT1);
186     PatchableJump notIndex = patchableBranch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag));
187     addSlowCase(notIndex);
188     emitArrayProfilingSiteWithCell(regT0, regT1, profile);
189     and32(TrustedImm32(IndexingShapeMask), regT1);
190
191     PatchableJump badType;
192     JumpList slowCases;
193     
194     JITArrayMode mode = chooseArrayMode(profile);
195     switch (mode) {
196     case JITInt32:
197         slowCases = emitInt32GetByVal(currentInstruction, badType);
198         break;
199     case JITDouble:
200         slowCases = emitDoubleGetByVal(currentInstruction, badType);
201         break;
202     case JITContiguous:
203         slowCases = emitContiguousGetByVal(currentInstruction, badType);
204         break;
205     case JITArrayStorage:
206         slowCases = emitArrayStorageGetByVal(currentInstruction, badType);
207         break;
208     default:
209         CRASH();
210     }
211     
212     addSlowCase(badType);
213     addSlowCase(slowCases);
214     
215     Label done = label();
216
217     if (!ASSERT_DISABLED) {
218         Jump resultOK = branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag));
219         abortWithReason(JITGetByValResultIsNotEmpty);
220         resultOK.link(this);
221     }
222
223     emitValueProfilingSite();
224     emitStore(dst, regT1, regT0);
225
226     Label nextHotPath = label();
227     
228     m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, notIndex, badType, mode, profile, done, nextHotPath));
229 }
230
231 JIT::JumpList JIT::emitContiguousLoad(Instruction*, PatchableJump& badType, IndexingType expectedShape)
232 {
233     JumpList slowCases;
234     
235     badType = patchableBranch32(NotEqual, regT1, TrustedImm32(expectedShape));
236     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
237     slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfPublicLength())));
238     load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
239     load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
240     slowCases.append(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
241     
242     return slowCases;
243 }
244
245 JIT::JumpList JIT::emitDoubleLoad(Instruction*, PatchableJump& badType)
246 {
247     JumpList slowCases;
248     
249     badType = patchableBranch32(NotEqual, regT1, TrustedImm32(DoubleShape));
250     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
251     slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfPublicLength())));
252     loadDouble(BaseIndex(regT3, regT2, TimesEight), fpRegT0);
253     slowCases.append(branchDouble(DoubleNotEqualOrUnordered, fpRegT0, fpRegT0));
254     
255     return slowCases;
256 }
257
258 JIT::JumpList JIT::emitArrayStorageLoad(Instruction*, PatchableJump& badType)
259 {
260     JumpList slowCases;
261     
262     add32(TrustedImm32(-ArrayStorageShape), regT1, regT3);
263     badType = patchableBranch32(Above, regT3, TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape));
264     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
265     slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset())));
266     load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
267     load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
268     slowCases.append(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
269     
270     return slowCases;
271 }
272
273 JITGetByIdGenerator JIT::emitGetByValWithCachedId(Instruction* currentInstruction, const Identifier& propertyName, Jump& fastDoneCase, Jump& slowDoneCase, JumpList& slowCases)
274 {
275     int dst = currentInstruction[1].u.operand;
276
277     // base: tag(regT1), payload(regT0)
278     // property: tag(regT3), payload(regT2)
279     // scratch: regT4
280
281     slowCases.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag)));
282     emitIdentifierCheck(regT2, regT4, propertyName, slowCases);
283
284     JITGetByIdGenerator gen(
285         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
286         JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0));
287     gen.generateFastPath(*this);
288
289     fastDoneCase = jump();
290
291     Label coldPathBegin = label();
292     gen.slowPathJump().link(this);
293
294     Call call = callOperation(WithProfile, operationGetByIdOptimize, dst, gen.stubInfo(), regT1, regT0, propertyName.impl());
295     gen.reportSlowPathCall(coldPathBegin, call);
296     slowDoneCase = jump();
297
298     return gen;
299 }
300
301 void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
302 {
303     int dst = currentInstruction[1].u.operand;
304     int base = currentInstruction[2].u.operand;
305     int property = currentInstruction[3].u.operand;
306     ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
307
308     linkSlowCaseIfNotJSCell(iter, base); // base cell check
309     linkSlowCase(iter); // property int32 check
310
311     Jump nonCell = jump();
312     linkSlowCase(iter); // base array check
313     Jump notString = branchStructure(NotEqual, Address(regT0, JSCell::structureIDOffset()), m_vm->stringStructure.get());
314     emitNakedCall(m_vm->getCTIStub(stringGetByValStubGenerator).code());
315     Jump failed = branchTestPtr(Zero, regT0);
316     emitStore(dst, regT1, regT0);
317     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
318     failed.link(this);
319     notString.link(this);
320     nonCell.link(this);
321
322     linkSlowCase(iter); // vector length check
323     linkSlowCase(iter); // empty value
324     
325     Label slowPath = label();
326     
327     emitLoad(base, regT1, regT0);
328     emitLoad(property, regT3, regT2);
329     Call call = callOperation(operationGetByValOptimize, dst, regT1, regT0, regT3, regT2, byValInfo);
330
331     m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
332     m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;
333     m_byValInstructionIndex++;
334
335     emitValueProfilingSite();
336 }
337
338 void JIT::emit_op_put_by_val(Instruction* currentInstruction)
339 {
340     int base = currentInstruction[1].u.operand;
341     int property = currentInstruction[2].u.operand;
342     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
343     ByValInfo* byValInfo = m_codeBlock->addByValInfo();
344     
345     emitLoad2(base, regT1, regT0, property, regT3, regT2);
346     
347     emitJumpSlowCaseIfNotJSCell(base, regT1);
348     PatchableJump notIndex = patchableBranch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag));
349     addSlowCase(notIndex);
350     emitArrayProfilingSiteWithCell(regT0, regT1, profile);
351     and32(TrustedImm32(IndexingShapeMask), regT1);
352     
353     PatchableJump badType;
354     JumpList slowCases;
355     
356     JITArrayMode mode = chooseArrayMode(profile);
357     switch (mode) {
358     case JITInt32:
359         slowCases = emitInt32PutByVal(currentInstruction, badType);
360         break;
361     case JITDouble:
362         slowCases = emitDoublePutByVal(currentInstruction, badType);
363         break;
364     case JITContiguous:
365         slowCases = emitContiguousPutByVal(currentInstruction, badType);
366         break;
367     case JITArrayStorage:
368         slowCases = emitArrayStoragePutByVal(currentInstruction, badType);
369         break;
370     default:
371         CRASH();
372         break;
373     }
374     
375     addSlowCase(badType);
376     addSlowCase(slowCases);
377     
378     Label done = label();
379     
380     m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, notIndex, badType, mode, profile, done, done));
381 }
382
383 JIT::JumpList JIT::emitGenericContiguousPutByVal(Instruction* currentInstruction, PatchableJump& badType, IndexingType indexingShape)
384 {
385     int base = currentInstruction[1].u.operand;
386     int value = currentInstruction[3].u.operand;
387     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
388     
389     JumpList slowCases;
390     
391     badType = patchableBranch32(NotEqual, regT1, TrustedImm32(ContiguousShape));
392     
393     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
394     Jump outOfBounds = branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfPublicLength()));
395     
396     Label storeResult = label();
397     emitLoad(value, regT1, regT0);
398     switch (indexingShape) {
399     case Int32Shape:
400         slowCases.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
401         store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
402         store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
403         break;
404     case ContiguousShape:
405         store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
406         store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
407         emitLoad(base, regT2, regT3);
408         emitWriteBarrier(base, value, ShouldFilterValue);
409         break;
410     case DoubleShape: {
411         Jump notInt = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
412         convertInt32ToDouble(regT0, fpRegT0);
413         Jump ready = jump();
414         notInt.link(this);
415         moveIntsToDouble(regT0, regT1, fpRegT0, fpRegT1);
416         slowCases.append(branchDouble(DoubleNotEqualOrUnordered, fpRegT0, fpRegT0));
417         ready.link(this);
418         storeDouble(fpRegT0, BaseIndex(regT3, regT2, TimesEight));
419         break;
420     }
421     default:
422         CRASH();
423         break;
424     }
425         
426     Jump done = jump();
427     
428     outOfBounds.link(this);
429     slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfVectorLength())));
430     
431     emitArrayProfileStoreToHoleSpecialCase(profile);
432     
433     add32(TrustedImm32(1), regT2, regT1);
434     store32(regT1, Address(regT3, Butterfly::offsetOfPublicLength()));
435     jump().linkTo(storeResult, this);
436     
437     done.link(this);
438     
439     return slowCases;
440 }
441
442 JIT::JumpList JIT::emitArrayStoragePutByVal(Instruction* currentInstruction, PatchableJump& badType)
443 {
444     int base = currentInstruction[1].u.operand;
445     int value = currentInstruction[3].u.operand;
446     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
447     
448     JumpList slowCases;
449     
450     badType = patchableBranch32(NotEqual, regT1, TrustedImm32(ArrayStorageShape));
451     
452     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
453     slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset())));
454
455     Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
456     
457     Label storeResult(this);
458     emitLoad(value, regT1, regT0);
459     store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); // payload
460     store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); // tag
461     Jump end = jump();
462     
463     empty.link(this);
464     emitArrayProfileStoreToHoleSpecialCase(profile);
465     add32(TrustedImm32(1), Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
466     branch32(Below, regT2, Address(regT3, ArrayStorage::lengthOffset())).linkTo(storeResult, this);
467     
468     add32(TrustedImm32(1), regT2, regT0);
469     store32(regT0, Address(regT3, ArrayStorage::lengthOffset()));
470     jump().linkTo(storeResult, this);
471     
472     end.link(this);
473     
474     emitWriteBarrier(base, value, ShouldFilterValue);
475     
476     return slowCases;
477 }
478
479 JITPutByIdGenerator JIT::emitPutByValWithCachedId(Instruction* currentInstruction, PutKind putKind, const Identifier& propertyName, JumpList& doneCases, JumpList& slowCases)
480 {
481     // base: tag(regT1), payload(regT0)
482     // property: tag(regT3), payload(regT2)
483
484     int base = currentInstruction[1].u.operand;
485     int value = currentInstruction[3].u.operand;
486
487     slowCases.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag)));
488     emitIdentifierCheck(regT2, regT2, propertyName, slowCases);
489
490     // Write barrier breaks the registers. So after issuing the write barrier,
491     // reload the registers.
492     emitWriteBarrier(base, value, ShouldFilterBase);
493     emitLoadPayload(base, regT0);
494     emitLoad(value, regT3, regT2);
495
496     JITPutByIdGenerator gen(
497         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
498         JSValueRegs::payloadOnly(regT0), JSValueRegs(regT3, regT2), regT1, m_codeBlock->ecmaMode(), putKind);
499     gen.generateFastPath(*this);
500     doneCases.append(jump());
501
502     Label coldPathBegin = label();
503     gen.slowPathJump().link(this);
504
505     // JITPutByIdGenerator only preserve the value and the base's payload, we have to reload the tag.
506     emitLoadTag(base, regT1);
507
508     Call call = callOperation(gen.slowPathFunction(), gen.stubInfo(), regT3, regT2, regT1, regT0, propertyName.impl());
509     gen.reportSlowPathCall(coldPathBegin, call);
510     doneCases.append(jump());
511
512     return gen;
513 }
514
515 void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
516 {
517     int base = currentInstruction[1].u.operand;
518     int property = currentInstruction[2].u.operand;
519     int value = currentInstruction[3].u.operand;
520     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
521     ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
522     
523     linkSlowCaseIfNotJSCell(iter, base); // base cell check
524     linkSlowCase(iter); // property int32 check
525     linkSlowCase(iter); // base not array check
526     
527     JITArrayMode mode = chooseArrayMode(profile);
528     switch (mode) {
529     case JITInt32:
530     case JITDouble:
531         linkSlowCase(iter); // value type check
532         break;
533     default:
534         break;
535     }
536     
537     Jump skipProfiling = jump();
538     linkSlowCase(iter); // out of bounds
539     emitArrayProfileOutOfBoundsSpecialCase(profile);
540     skipProfiling.link(this);
541
542     Label slowPath = label();
543     
544     bool isDirect = m_interpreter->getOpcodeID(currentInstruction->u.opcode) == op_put_by_val_direct;
545
546 #if CPU(X86)
547     // FIXME: We only have 5 temp registers, but need 6 to make this call, therefore we materialize
548     // our own call. When we finish moving JSC to the C call stack, we'll get another register so
549     // we can use the normal case.
550     resetCallArguments();
551     addCallArgument(GPRInfo::callFrameRegister);
552     emitLoad(base, regT0, regT1);
553     addCallArgument(regT1);
554     addCallArgument(regT0);
555     emitLoad(property, regT0, regT1);
556     addCallArgument(regT1);
557     addCallArgument(regT0);
558     emitLoad(value, regT0, regT1);
559     addCallArgument(regT1);
560     addCallArgument(regT0);
561     addCallArgument(TrustedImmPtr(byValInfo));
562     Call call = appendCallWithExceptionCheck(isDirect ? operationDirectPutByValOptimize : operationPutByValOptimize);
563 #else
564     // The register selection below is chosen to reduce register swapping on ARM.
565     // Swapping shouldn't happen on other platforms.
566     emitLoad(base, regT2, regT1);
567     emitLoad(property, regT3, regT0);
568     emitLoad(value, regT5, regT4);
569     Call call = callOperation(isDirect ? operationDirectPutByValOptimize : operationPutByValOptimize, regT2, regT1, regT3, regT0, regT5, regT4, byValInfo);
570 #endif
571
572     m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
573     m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;
574     m_byValInstructionIndex++;
575 }
576
577 void JIT::emit_op_get_by_id(Instruction* currentInstruction)
578 {
579     int dst = currentInstruction[1].u.operand;
580     int base = currentInstruction[2].u.operand;
581     const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
582     
583     emitLoad(base, regT1, regT0);
584     emitJumpSlowCaseIfNotJSCell(base, regT1);
585
586     if (*ident == m_vm->propertyNames->length && shouldEmitProfiling())
587         emitArrayProfilingSiteForBytecodeIndexWithCell(regT0, regT2, m_bytecodeOffset);
588
589     JITGetByIdGenerator gen(
590         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
591         JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0));
592     gen.generateFastPath(*this);
593     addSlowCase(gen.slowPathJump());
594     m_getByIds.append(gen);
595
596     emitValueProfilingSite();
597     emitStore(dst, regT1, regT0);
598 }
599
600 void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
601 {
602     int resultVReg = currentInstruction[1].u.operand;
603     int baseVReg = currentInstruction[2].u.operand;
604     const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
605
606     linkSlowCaseIfNotJSCell(iter, baseVReg);
607     linkSlowCase(iter);
608
609     JITGetByIdGenerator& gen = m_getByIds[m_getByIdIndex++];
610     
611     Label coldPathBegin = label();
612     
613     Call call = callOperation(WithProfile, operationGetByIdOptimize, resultVReg, gen.stubInfo(), regT1, regT0, ident->impl());
614     
615     gen.reportSlowPathCall(coldPathBegin, call);
616 }
617
618 void JIT::emit_op_put_by_id(Instruction* currentInstruction)
619 {
620     // In order to be able to patch both the Structure, and the object offset, we store one pointer,
621     // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code
622     // such that the Structure & offset are always at the same distance from this.
623     
624     int base = currentInstruction[1].u.operand;
625     int value = currentInstruction[3].u.operand;
626     int direct = currentInstruction[8].u.putByIdFlags & PutByIdIsDirect;
627     
628     emitWriteBarrier(base, value, ShouldFilterBase);
629
630     emitLoad2(base, regT1, regT0, value, regT3, regT2);
631     
632     emitJumpSlowCaseIfNotJSCell(base, regT1);
633
634     JITPutByIdGenerator gen(
635         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
636         JSValueRegs::payloadOnly(regT0), JSValueRegs(regT3, regT2),
637         regT1, m_codeBlock->ecmaMode(), direct ? Direct : NotDirect);
638     
639     gen.generateFastPath(*this);
640     addSlowCase(gen.slowPathJump());
641     
642     m_putByIds.append(gen);
643 }
644
645 void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
646 {
647     int base = currentInstruction[1].u.operand;
648     const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
649
650     linkSlowCaseIfNotJSCell(iter, base);
651     linkSlowCase(iter);
652     
653     Label coldPathBegin(this);
654
655     // JITPutByIdGenerator only preserve the value and the base's payload, we have to reload the tag.
656     emitLoadTag(base, regT1);
657
658     JITPutByIdGenerator& gen = m_putByIds[m_putByIdIndex++];
659     
660     Call call = callOperation(
661         gen.slowPathFunction(), gen.stubInfo(), regT3, regT2, regT1, regT0, ident->impl());
662     
663     gen.reportSlowPathCall(coldPathBegin, call);
664 }
665
666 void JIT::emitVarInjectionCheck(bool needsVarInjectionChecks)
667 {
668     if (!needsVarInjectionChecks)
669         return;
670     addSlowCase(branch8(Equal, AbsoluteAddress(m_codeBlock->globalObject()->varInjectionWatchpoint()->addressOfState()), TrustedImm32(IsInvalidated)));
671 }
672
673 void JIT::emitResolveClosure(int dst, int scope, bool needsVarInjectionChecks, unsigned depth)
674 {
675     emitVarInjectionCheck(needsVarInjectionChecks);
676     move(TrustedImm32(JSValue::CellTag), regT1);
677     emitLoadPayload(scope, regT0);
678     for (unsigned i = 0; i < depth; ++i)
679         loadPtr(Address(regT0, JSScope::offsetOfNext()), regT0);
680     emitStore(dst, regT1, regT0);
681 }
682
683 void JIT::emit_op_resolve_scope(Instruction* currentInstruction)
684 {
685     int dst = currentInstruction[1].u.operand;
686     int scope = currentInstruction[2].u.operand;
687     ResolveType resolveType = static_cast<ResolveType>(currentInstruction[4].u.operand);
688     unsigned depth = currentInstruction[5].u.operand;
689     auto emitCode = [&] (ResolveType resolveType) {
690         switch (resolveType) {
691         case GlobalProperty:
692         case GlobalVar:
693         case GlobalLexicalVar:
694         case GlobalPropertyWithVarInjectionChecks:
695         case GlobalVarWithVarInjectionChecks: 
696         case GlobalLexicalVarWithVarInjectionChecks: {
697             JSScope* constantScope = JSScope::constantScopeForCodeBlock(resolveType, m_codeBlock);
698             RELEASE_ASSERT(constantScope);
699             emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
700             move(TrustedImm32(JSValue::CellTag), regT1);
701             move(TrustedImmPtr(constantScope), regT0);
702             emitStore(dst, regT1, regT0);
703             break;
704         }
705         case ClosureVar:
706         case ClosureVarWithVarInjectionChecks:
707             emitResolveClosure(dst, scope, needsVarInjectionChecks(resolveType), depth);
708             break;
709         case ModuleVar:
710             move(TrustedImm32(JSValue::CellTag), regT1);
711             move(TrustedImmPtr(currentInstruction[6].u.jsCell.get()), regT0);
712             emitStore(dst, regT1, regT0);
713             break;
714         case Dynamic:
715             addSlowCase(jump());
716             break;
717         case LocalClosureVar:
718         case UnresolvedProperty:
719         case UnresolvedPropertyWithVarInjectionChecks:
720             RELEASE_ASSERT_NOT_REACHED();
721         }
722     };
723     switch (resolveType) {
724     case UnresolvedProperty:
725     case UnresolvedPropertyWithVarInjectionChecks: {
726         JumpList skipToEnd;
727         load32(&currentInstruction[4], regT0);
728
729         Jump notGlobalProperty = branch32(NotEqual, regT0, TrustedImm32(GlobalProperty));
730         emitCode(GlobalProperty);
731         skipToEnd.append(jump());
732         notGlobalProperty.link(this);
733
734         Jump notGlobalPropertyWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalPropertyWithVarInjectionChecks));
735         emitCode(GlobalPropertyWithVarInjectionChecks);
736         skipToEnd.append(jump());
737         notGlobalPropertyWithVarInjections.link(this);
738
739         Jump notGlobalLexicalVar = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVar));
740         emitCode(GlobalLexicalVar);
741         skipToEnd.append(jump());
742         notGlobalLexicalVar.link(this);
743
744         Jump notGlobalLexicalVarWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVarWithVarInjectionChecks));
745         emitCode(GlobalLexicalVarWithVarInjectionChecks);
746         skipToEnd.append(jump());
747         notGlobalLexicalVarWithVarInjections.link(this);
748
749         addSlowCase(jump());
750         skipToEnd.link(this);
751         break;
752     }
753
754     default:
755         emitCode(resolveType);
756         break;
757     }
758 }
759
760 void JIT::emitSlow_op_resolve_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
761 {
762     ResolveType resolveType = static_cast<ResolveType>(currentInstruction[4].u.operand);
763
764     if (resolveType == GlobalProperty || resolveType == GlobalVar || resolveType == ClosureVar || resolveType == GlobalLexicalVar || resolveType == ModuleVar)
765         return;
766     if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
767         linkSlowCase(iter); // Var injections check for GlobalPropertyWithVarInjectionChecks.
768         linkSlowCase(iter); // Var injections check for GlobalLexicalVarWithVarInjectionChecks.
769     }
770
771     linkSlowCase(iter);
772     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_resolve_scope);
773     slowPathCall.call();
774 }
775
776 void JIT::emitLoadWithStructureCheck(int scope, Structure** structureSlot)
777 {
778     emitLoad(scope, regT1, regT0);
779     loadPtr(structureSlot, regT2);
780     addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::structureIDOffset()), regT2));
781 }
782
783 void JIT::emitGetVarFromPointer(JSValue* operand, GPRReg tag, GPRReg payload)
784 {
785     uintptr_t rawAddress = bitwise_cast<uintptr_t>(operand);
786     load32(bitwise_cast<void*>(rawAddress + TagOffset), tag);
787     load32(bitwise_cast<void*>(rawAddress + PayloadOffset), payload);
788 }
789 void JIT::emitGetVarFromIndirectPointer(JSValue** operand, GPRReg tag, GPRReg payload)
790 {
791     loadPtr(operand, payload);
792     load32(Address(payload, TagOffset), tag);
793     load32(Address(payload, PayloadOffset), payload);
794 }
795
796 void JIT::emitGetClosureVar(int scope, uintptr_t operand)
797 {
798     emitLoad(scope, regT1, regT0);
799     load32(Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + TagOffset), regT1);
800     load32(Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + PayloadOffset), regT0);
801 }
802
803 void JIT::emit_op_get_from_scope(Instruction* currentInstruction)
804 {
805     int dst = currentInstruction[1].u.operand;
806     int scope = currentInstruction[2].u.operand;
807     ResolveType resolveType = GetPutInfo(currentInstruction[4].u.operand).resolveType();
808     Structure** structureSlot = currentInstruction[5].u.structure.slot();
809     uintptr_t* operandSlot = reinterpret_cast<uintptr_t*>(&currentInstruction[6].u.pointer);
810     
811     auto emitCode = [&] (ResolveType resolveType, bool indirectLoadForOperand) {
812         switch (resolveType) {
813         case GlobalProperty:
814         case GlobalPropertyWithVarInjectionChecks: {
815             emitLoadWithStructureCheck(scope, structureSlot); // Structure check covers var injection.
816             GPRReg base = regT2;
817             GPRReg resultTag = regT1;
818             GPRReg resultPayload = regT0;
819             GPRReg offset = regT3;
820             
821             move(regT0, base);
822             load32(operandSlot, offset);
823             if (!ASSERT_DISABLED) {
824                 Jump isOutOfLine = branch32(GreaterThanOrEqual, offset, TrustedImm32(firstOutOfLineOffset));
825                 abortWithReason(JITOffsetIsNotOutOfLine);
826                 isOutOfLine.link(this);
827             }
828             loadPtr(Address(base, JSObject::butterflyOffset()), base);
829             neg32(offset);
830             load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)), resultPayload);
831             load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)), resultTag);
832             break;
833         }
834         case GlobalVar:
835         case GlobalVarWithVarInjectionChecks:
836         case GlobalLexicalVar:
837         case GlobalLexicalVarWithVarInjectionChecks:
838             emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
839             if (indirectLoadForOperand)
840                 emitGetVarFromIndirectPointer(bitwise_cast<JSValue**>(operandSlot), regT1, regT0);
841             else
842                 emitGetVarFromPointer(bitwise_cast<JSValue*>(*operandSlot), regT1, regT0);
843             if (resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks) // TDZ check.
844                 addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
845             break;
846         case ClosureVar:
847         case ClosureVarWithVarInjectionChecks:
848             emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
849             emitGetClosureVar(scope, *operandSlot);
850             break;
851         case Dynamic:
852             addSlowCase(jump());
853             break;
854         case ModuleVar:
855         case LocalClosureVar:
856         case UnresolvedProperty:
857         case UnresolvedPropertyWithVarInjectionChecks:
858             RELEASE_ASSERT_NOT_REACHED();
859         }
860     };
861
862     switch (resolveType) {
863     case UnresolvedProperty:
864     case UnresolvedPropertyWithVarInjectionChecks: {
865         JumpList skipToEnd;
866         load32(&currentInstruction[4], regT0);
867         and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
868
869         Jump isGlobalProperty = branch32(Equal, regT0, TrustedImm32(GlobalProperty));
870         Jump notGlobalPropertyWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalPropertyWithVarInjectionChecks));
871         isGlobalProperty.link(this);
872         emitCode(GlobalProperty, false);
873         skipToEnd.append(jump());
874         notGlobalPropertyWithVarInjections.link(this);
875
876         Jump notGlobalLexicalVar = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVar));
877         emitCode(GlobalLexicalVar, true);
878         skipToEnd.append(jump());
879         notGlobalLexicalVar.link(this);
880
881         Jump notGlobalLexicalVarWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVarWithVarInjectionChecks));
882         emitCode(GlobalLexicalVarWithVarInjectionChecks, true);
883         skipToEnd.append(jump());
884         notGlobalLexicalVarWithVarInjections.link(this);
885
886         addSlowCase(jump());
887
888         skipToEnd.link(this);
889         break;
890     }
891
892     default:
893         emitCode(resolveType, false);
894         break;
895     }
896     emitValueProfilingSite();
897     emitStore(dst, regT1, regT0);
898 }
899
900 void JIT::emitSlow_op_get_from_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
901 {
902     int dst = currentInstruction[1].u.operand;
903     ResolveType resolveType = GetPutInfo(currentInstruction[4].u.operand).resolveType();
904
905     if (resolveType == GlobalVar || resolveType == ClosureVar)
906         return;
907
908     if (resolveType == GlobalLexicalVarWithVarInjectionChecks) // Var Injections check.
909         linkSlowCase(iter);
910
911     if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
912         // GlobalProperty/GlobalPropertyWithVarInjectionChecks
913         linkSlowCase(iter); // emitLoadWithStructureCheck
914         // GlobalLexicalVar
915         linkSlowCase(iter); // TDZ check.
916         // GlobalLexicalVarWithVarInjectionChecks.
917         linkSlowCase(iter); // var injection check.
918         linkSlowCase(iter); // TDZ check.
919     }
920
921     linkSlowCase(iter);
922     callOperation(WithProfile, operationGetFromScope, dst, currentInstruction);
923 }
924
925 void JIT::emitPutGlobalVariable(JSValue* operand, int value, WatchpointSet* set)
926 {
927     emitLoad(value, regT1, regT0);
928     emitNotifyWrite(set);
929     uintptr_t rawAddress = bitwise_cast<uintptr_t>(operand);
930     store32(regT1, bitwise_cast<void*>(rawAddress + TagOffset));
931     store32(regT0, bitwise_cast<void*>(rawAddress + PayloadOffset));
932 }
933
934 void JIT::emitPutGlobalVariableIndirect(JSValue** addressOfOperand, int value, WatchpointSet** indirectWatchpointSet)
935 {
936     emitLoad(value, regT1, regT0);
937     loadPtr(indirectWatchpointSet, regT2);
938     emitNotifyWrite(regT2);
939     loadPtr(addressOfOperand, regT2);
940     store32(regT1, Address(regT2, TagOffset));
941     store32(regT0, Address(regT2, PayloadOffset));
942 }
943
944 void JIT::emitPutClosureVar(int scope, uintptr_t operand, int value, WatchpointSet* set)
945 {
946     emitLoad(value, regT3, regT2);
947     emitLoad(scope, regT1, regT0);
948     emitNotifyWrite(set);
949     store32(regT3, Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + TagOffset));
950     store32(regT2, Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + PayloadOffset));
951 }
952
953 void JIT::emit_op_put_to_scope(Instruction* currentInstruction)
954 {
955     int scope = currentInstruction[1].u.operand;
956     int value = currentInstruction[3].u.operand;
957     GetPutInfo getPutInfo = GetPutInfo(currentInstruction[4].u.operand);
958     ResolveType resolveType = getPutInfo.resolveType();
959     Structure** structureSlot = currentInstruction[5].u.structure.slot();
960     uintptr_t* operandSlot = reinterpret_cast<uintptr_t*>(&currentInstruction[6].u.pointer);
961     
962     auto emitCode = [&] (ResolveType resolveType, bool indirectLoadForOperand) {
963         switch (resolveType) {
964         case GlobalProperty:
965         case GlobalPropertyWithVarInjectionChecks: {
966             emitWriteBarrier(m_codeBlock->globalObject(), value, ShouldFilterValue);
967             emitLoadWithStructureCheck(scope, structureSlot); // Structure check covers var injection.
968             emitLoad(value, regT3, regT2);
969             
970             loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
971             loadPtr(operandSlot, regT1);
972             negPtr(regT1);
973             store32(regT3, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
974             store32(regT2, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
975             break;
976         }
977         case GlobalVar:
978         case GlobalVarWithVarInjectionChecks:
979         case GlobalLexicalVar:
980         case GlobalLexicalVarWithVarInjectionChecks: {
981             JSScope* constantScope = JSScope::constantScopeForCodeBlock(resolveType, m_codeBlock);
982             RELEASE_ASSERT(constantScope);
983             emitWriteBarrier(constantScope, value, ShouldFilterValue);
984             emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
985             if (getPutInfo.initializationMode() != Initialization && (resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks)) {
986                 // We need to do a TDZ check here because we can't always prove we need to emit TDZ checks statically.
987                 if (indirectLoadForOperand)
988                     emitGetVarFromIndirectPointer(bitwise_cast<JSValue**>(operandSlot), regT1, regT0);
989                 else
990                     emitGetVarFromPointer(bitwise_cast<JSValue*>(*operandSlot), regT1, regT0);
991                 addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
992             }
993             if (indirectLoadForOperand)
994                 emitPutGlobalVariableIndirect(bitwise_cast<JSValue**>(operandSlot), value, bitwise_cast<WatchpointSet**>(&currentInstruction[5]));
995             else
996                 emitPutGlobalVariable(bitwise_cast<JSValue*>(*operandSlot), value, currentInstruction[5].u.watchpointSet);
997             break;
998         }
999         case LocalClosureVar:
1000         case ClosureVar:
1001         case ClosureVarWithVarInjectionChecks:
1002             emitWriteBarrier(scope, value, ShouldFilterValue);
1003             emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
1004             emitPutClosureVar(scope, *operandSlot, value, currentInstruction[5].u.watchpointSet);
1005             break;
1006         case ModuleVar:
1007         case Dynamic:
1008             addSlowCase(jump());
1009             break;
1010         case UnresolvedProperty:
1011         case UnresolvedPropertyWithVarInjectionChecks:
1012             RELEASE_ASSERT_NOT_REACHED();
1013         }
1014     };
1015
1016     switch (resolveType) {
1017     case UnresolvedProperty:
1018     case UnresolvedPropertyWithVarInjectionChecks: {
1019         JumpList skipToEnd;
1020         load32(&currentInstruction[4], regT0);
1021         and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
1022
1023         Jump isGlobalProperty = branch32(Equal, regT0, TrustedImm32(GlobalProperty));
1024         Jump notGlobalPropertyWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalPropertyWithVarInjectionChecks));
1025         isGlobalProperty.link(this);
1026         emitCode(GlobalProperty, false);
1027         skipToEnd.append(jump());
1028         notGlobalPropertyWithVarInjections.link(this);
1029
1030         Jump notGlobalLexicalVar = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVar));
1031         emitCode(GlobalLexicalVar, true);
1032         skipToEnd.append(jump());
1033         notGlobalLexicalVar.link(this);
1034
1035         Jump notGlobalLexicalVarWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVarWithVarInjectionChecks));
1036         emitCode(GlobalLexicalVarWithVarInjectionChecks, true);
1037         skipToEnd.append(jump());
1038         notGlobalLexicalVarWithVarInjections.link(this);
1039
1040         addSlowCase(jump());
1041
1042         skipToEnd.link(this);
1043         break;
1044     }
1045
1046     default:
1047         emitCode(resolveType, false);
1048         break;
1049     }
1050 }
1051
1052 void JIT::emitSlow_op_put_to_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1053 {
1054     GetPutInfo getPutInfo = GetPutInfo(currentInstruction[4].u.operand);
1055     ResolveType resolveType = getPutInfo.resolveType();
1056     unsigned linkCount = 0;
1057     if (resolveType != GlobalVar && resolveType != ClosureVar && resolveType != LocalClosureVar && resolveType != GlobalLexicalVar)
1058         linkCount++;
1059     if ((resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks || resolveType == LocalClosureVar
1060         || resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks)
1061         && currentInstruction[5].u.watchpointSet->state() != IsInvalidated)
1062         linkCount++;
1063     if (getPutInfo.initializationMode() != Initialization && (resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks)) // TDZ check.
1064         linkCount++;
1065     if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
1066         // GlobalProperty/GlobalPropertyWithVarInjectionsCheck
1067         linkCount++; // emitLoadWithStructureCheck
1068
1069         // GlobalLexicalVar
1070         bool needsTDZCheck = getPutInfo.initializationMode() != Initialization;
1071         if (needsTDZCheck)
1072             linkCount++;
1073         linkCount++; // Notify write check.
1074
1075         // GlobalLexicalVarWithVarInjectionsCheck
1076         linkCount++; // var injection check.
1077         if (needsTDZCheck)
1078             linkCount++;
1079         linkCount++; // Notify write check.
1080     }
1081     if (!linkCount)
1082         return;
1083     while (linkCount--)
1084         linkSlowCase(iter);
1085
1086     if (resolveType == ModuleVar) {
1087         JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_throw_strict_mode_readonly_property_write_error);
1088         slowPathCall.call();
1089     } else
1090         callOperation(operationPutToScope, currentInstruction);
1091 }
1092
1093 void JIT::emit_op_get_from_arguments(Instruction* currentInstruction)
1094 {
1095     int dst = currentInstruction[1].u.operand;
1096     int arguments = currentInstruction[2].u.operand;
1097     int index = currentInstruction[3].u.operand;
1098     
1099     emitLoadPayload(arguments, regT0);
1100     load32(Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + TagOffset), regT1);
1101     load32(Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + PayloadOffset), regT0);
1102     emitValueProfilingSite();
1103     emitStore(dst, regT1, regT0);
1104 }
1105
1106 void JIT::emit_op_put_to_arguments(Instruction* currentInstruction)
1107 {
1108     int arguments = currentInstruction[1].u.operand;
1109     int index = currentInstruction[2].u.operand;
1110     int value = currentInstruction[3].u.operand;
1111     
1112     emitWriteBarrier(arguments, value, ShouldFilterValue);
1113     
1114     emitLoadPayload(arguments, regT0);
1115     emitLoad(value, regT1, regT2);
1116     store32(regT1, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + TagOffset));
1117     store32(regT2, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + PayloadOffset));
1118 }
1119
1120 } // namespace JSC
1121
1122 #endif // USE(JSVALUE32_64)
1123 #endif // ENABLE(JIT)