226f71a01d5531ca8ec83f93ed0cbacf6de040c9
[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), DontSpill);
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, DontSpill, 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), DontSpill);
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, DontSpill, 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::emitGetGlobalProperty(uintptr_t* operandSlot)
784 {
785     GPRReg base = regT2;
786     GPRReg resultTag = regT1;
787     GPRReg resultPayload = regT0;
788     GPRReg offset = regT3;
789     
790     move(regT0, base);
791     load32(operandSlot, offset);
792     if (!ASSERT_DISABLED) {
793         Jump isOutOfLine = branch32(GreaterThanOrEqual, offset, TrustedImm32(firstOutOfLineOffset));
794         abortWithReason(JITOffsetIsNotOutOfLine);
795         isOutOfLine.link(this);
796     }
797     loadPtr(Address(base, JSObject::butterflyOffset()), base);
798     neg32(offset);
799     load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)), resultPayload);
800     load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)), resultTag);
801 }
802
803 void JIT::emitGetVarFromPointer(JSValue* operand, GPRReg tag, GPRReg payload)
804 {
805     uintptr_t rawAddress = bitwise_cast<uintptr_t>(operand);
806     load32(bitwise_cast<void*>(rawAddress + TagOffset), tag);
807     load32(bitwise_cast<void*>(rawAddress + PayloadOffset), payload);
808 }
809 void JIT::emitGetVarFromIndirectPointer(JSValue** operand, GPRReg tag, GPRReg payload)
810 {
811     loadPtr(operand, payload);
812     load32(Address(payload, TagOffset), tag);
813     load32(Address(payload, PayloadOffset), payload);
814 }
815
816 void JIT::emitGetClosureVar(int scope, uintptr_t operand)
817 {
818     emitLoad(scope, regT1, regT0);
819     load32(Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + TagOffset), regT1);
820     load32(Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + PayloadOffset), regT0);
821 }
822
823 void JIT::emit_op_get_from_scope(Instruction* currentInstruction)
824 {
825     int dst = currentInstruction[1].u.operand;
826     int scope = currentInstruction[2].u.operand;
827     ResolveType resolveType = GetPutInfo(currentInstruction[4].u.operand).resolveType();
828     Structure** structureSlot = currentInstruction[5].u.structure.slot();
829     uintptr_t* operandSlot = reinterpret_cast<uintptr_t*>(&currentInstruction[6].u.pointer);
830     
831     auto emitCode = [&] (ResolveType resolveType, bool indirectLoadForOperand) {
832         switch (resolveType) {
833         case GlobalProperty:
834         case GlobalPropertyWithVarInjectionChecks:
835             emitLoadWithStructureCheck(scope, structureSlot); // Structure check covers var injection.
836             emitGetGlobalProperty(operandSlot);
837             break;
838         case GlobalVar:
839         case GlobalVarWithVarInjectionChecks:
840         case GlobalLexicalVar:
841         case GlobalLexicalVarWithVarInjectionChecks:
842             emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
843             if (indirectLoadForOperand)
844                 emitGetVarFromIndirectPointer(bitwise_cast<JSValue**>(operandSlot), regT1, regT0);
845             else
846                 emitGetVarFromPointer(bitwise_cast<JSValue*>(*operandSlot), regT1, regT0);
847             if (resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks) // TDZ check.
848                 addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
849             break;
850         case ClosureVar:
851         case ClosureVarWithVarInjectionChecks:
852             emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
853             emitGetClosureVar(scope, *operandSlot);
854             break;
855         case Dynamic:
856             addSlowCase(jump());
857             break;
858         case ModuleVar:
859         case LocalClosureVar:
860         case UnresolvedProperty:
861         case UnresolvedPropertyWithVarInjectionChecks:
862             RELEASE_ASSERT_NOT_REACHED();
863         }
864     };
865
866     switch (resolveType) {
867     case UnresolvedProperty:
868     case UnresolvedPropertyWithVarInjectionChecks: {
869         JumpList skipToEnd;
870         load32(&currentInstruction[4], regT0);
871         and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
872
873         Jump isGlobalProperty = branch32(Equal, regT0, TrustedImm32(GlobalProperty));
874         Jump notGlobalPropertyWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalPropertyWithVarInjectionChecks));
875         isGlobalProperty.link(this);
876         emitCode(GlobalProperty, false);
877         skipToEnd.append(jump());
878         notGlobalPropertyWithVarInjections.link(this);
879
880         Jump notGlobalLexicalVar = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVar));
881         emitCode(GlobalLexicalVar, true);
882         skipToEnd.append(jump());
883         notGlobalLexicalVar.link(this);
884
885         Jump notGlobalLexicalVarWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVarWithVarInjectionChecks));
886         emitCode(GlobalLexicalVarWithVarInjectionChecks, true);
887         skipToEnd.append(jump());
888         notGlobalLexicalVarWithVarInjections.link(this);
889
890         addSlowCase(jump());
891
892         skipToEnd.link(this);
893         break;
894     }
895
896     default:
897         emitCode(resolveType, false);
898         break;
899     }
900     emitValueProfilingSite();
901     emitStore(dst, regT1, regT0);
902 }
903
904 void JIT::emitSlow_op_get_from_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
905 {
906     int dst = currentInstruction[1].u.operand;
907     ResolveType resolveType = GetPutInfo(currentInstruction[4].u.operand).resolveType();
908
909     if (resolveType == GlobalVar || resolveType == ClosureVar)
910         return;
911
912     if (resolveType == GlobalLexicalVarWithVarInjectionChecks) // Var Injections check.
913         linkSlowCase(iter);
914
915     if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
916         // GlobalProperty/GlobalPropertyWithVarInjectionChecks
917         linkSlowCase(iter); // emitLoadWithStructureCheck
918         // GlobalLexicalVar
919         linkSlowCase(iter); // TDZ check.
920         // GlobalLexicalVarWithVarInjectionChecks.
921         linkSlowCase(iter); // var injection check.
922         linkSlowCase(iter); // TDZ check.
923     }
924
925     linkSlowCase(iter);
926     callOperation(WithProfile, operationGetFromScope, dst, currentInstruction);
927 }
928
929 void JIT::emitPutGlobalProperty(uintptr_t* operandSlot, int value)
930 {
931     emitLoad(value, regT3, regT2);
932     
933     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
934     loadPtr(operandSlot, regT1);
935     negPtr(regT1);
936     store32(regT3, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
937     store32(regT2, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
938 }
939
940 void JIT::emitPutGlobalVariable(JSValue* operand, int value, WatchpointSet* set)
941 {
942     emitLoad(value, regT1, regT0);
943     emitNotifyWrite(set);
944     uintptr_t rawAddress = bitwise_cast<uintptr_t>(operand);
945     store32(regT1, bitwise_cast<void*>(rawAddress + TagOffset));
946     store32(regT0, bitwise_cast<void*>(rawAddress + PayloadOffset));
947 }
948
949 void JIT::emitPutGlobalVariableIndirect(JSValue** addressOfOperand, int value, WatchpointSet** indirectWatchpointSet)
950 {
951     emitLoad(value, regT1, regT0);
952     loadPtr(indirectWatchpointSet, regT2);
953     emitNotifyWrite(regT2);
954     loadPtr(addressOfOperand, regT2);
955     store32(regT1, Address(regT2, TagOffset));
956     store32(regT0, Address(regT2, PayloadOffset));
957 }
958
959 void JIT::emitPutClosureVar(int scope, uintptr_t operand, int value, WatchpointSet* set)
960 {
961     emitLoad(value, regT3, regT2);
962     emitLoad(scope, regT1, regT0);
963     emitNotifyWrite(set);
964     store32(regT3, Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + TagOffset));
965     store32(regT2, Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + PayloadOffset));
966 }
967
968 void JIT::emit_op_put_to_scope(Instruction* currentInstruction)
969 {
970     int scope = currentInstruction[1].u.operand;
971     int value = currentInstruction[3].u.operand;
972     GetPutInfo getPutInfo = GetPutInfo(currentInstruction[4].u.operand);
973     ResolveType resolveType = getPutInfo.resolveType();
974     Structure** structureSlot = currentInstruction[5].u.structure.slot();
975     uintptr_t* operandSlot = reinterpret_cast<uintptr_t*>(&currentInstruction[6].u.pointer);
976     
977     auto emitCode = [&] (ResolveType resolveType, bool indirectLoadForOperand) {
978         switch (resolveType) {
979         case GlobalProperty:
980         case GlobalPropertyWithVarInjectionChecks:
981             emitWriteBarrier(m_codeBlock->globalObject(), value, ShouldFilterValue);
982             emitLoadWithStructureCheck(scope, structureSlot); // Structure check covers var injection.
983             emitPutGlobalProperty(operandSlot, value);
984             break;
985         case GlobalVar:
986         case GlobalVarWithVarInjectionChecks:
987         case GlobalLexicalVar:
988         case GlobalLexicalVarWithVarInjectionChecks: {
989             JSScope* constantScope = JSScope::constantScopeForCodeBlock(resolveType, m_codeBlock);
990             RELEASE_ASSERT(constantScope);
991             emitWriteBarrier(constantScope, value, ShouldFilterValue);
992             emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
993             if (getPutInfo.initializationMode() != Initialization && (resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks)) {
994                 // We need to do a TDZ check here because we can't always prove we need to emit TDZ checks statically.
995                 if (indirectLoadForOperand)
996                     emitGetVarFromIndirectPointer(bitwise_cast<JSValue**>(operandSlot), regT1, regT0);
997                 else
998                     emitGetVarFromPointer(bitwise_cast<JSValue*>(*operandSlot), regT1, regT0);
999                 addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
1000             }
1001             if (indirectLoadForOperand)
1002                 emitPutGlobalVariableIndirect(bitwise_cast<JSValue**>(operandSlot), value, bitwise_cast<WatchpointSet**>(&currentInstruction[5]));
1003             else
1004                 emitPutGlobalVariable(bitwise_cast<JSValue*>(*operandSlot), value, currentInstruction[5].u.watchpointSet);
1005             break;
1006         }
1007         case LocalClosureVar:
1008         case ClosureVar:
1009         case ClosureVarWithVarInjectionChecks:
1010             emitWriteBarrier(scope, value, ShouldFilterValue);
1011             emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
1012             emitPutClosureVar(scope, *operandSlot, value, currentInstruction[5].u.watchpointSet);
1013             break;
1014         case ModuleVar:
1015         case Dynamic:
1016             addSlowCase(jump());
1017             break;
1018         case UnresolvedProperty:
1019         case UnresolvedPropertyWithVarInjectionChecks:
1020             RELEASE_ASSERT_NOT_REACHED();
1021         }
1022     };
1023
1024     switch (resolveType) {
1025     case UnresolvedProperty:
1026     case UnresolvedPropertyWithVarInjectionChecks: {
1027         JumpList skipToEnd;
1028         load32(&currentInstruction[4], regT0);
1029         and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
1030
1031         Jump isGlobalProperty = branch32(Equal, regT0, TrustedImm32(GlobalProperty));
1032         Jump notGlobalPropertyWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalPropertyWithVarInjectionChecks));
1033         isGlobalProperty.link(this);
1034         emitCode(GlobalProperty, false);
1035         skipToEnd.append(jump());
1036         notGlobalPropertyWithVarInjections.link(this);
1037
1038         Jump notGlobalLexicalVar = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVar));
1039         emitCode(GlobalLexicalVar, true);
1040         skipToEnd.append(jump());
1041         notGlobalLexicalVar.link(this);
1042
1043         Jump notGlobalLexicalVarWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVarWithVarInjectionChecks));
1044         emitCode(GlobalLexicalVarWithVarInjectionChecks, true);
1045         skipToEnd.append(jump());
1046         notGlobalLexicalVarWithVarInjections.link(this);
1047
1048         addSlowCase(jump());
1049
1050         skipToEnd.link(this);
1051         break;
1052     }
1053
1054     default:
1055         emitCode(resolveType, false);
1056         break;
1057     }
1058 }
1059
1060 void JIT::emitSlow_op_put_to_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1061 {
1062     GetPutInfo getPutInfo = GetPutInfo(currentInstruction[4].u.operand);
1063     ResolveType resolveType = getPutInfo.resolveType();
1064     unsigned linkCount = 0;
1065     if (resolveType != GlobalVar && resolveType != ClosureVar && resolveType != LocalClosureVar && resolveType != GlobalLexicalVar)
1066         linkCount++;
1067     if ((resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks || resolveType == LocalClosureVar
1068         || resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks)
1069         && currentInstruction[5].u.watchpointSet->state() != IsInvalidated)
1070         linkCount++;
1071     if (getPutInfo.initializationMode() != Initialization && (resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks)) // TDZ check.
1072         linkCount++;
1073     if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
1074         // GlobalProperty/GlobalPropertyWithVarInjectionsCheck
1075         linkCount++; // emitLoadWithStructureCheck
1076
1077         // GlobalLexicalVar
1078         bool needsTDZCheck = getPutInfo.initializationMode() != Initialization;
1079         if (needsTDZCheck)
1080             linkCount++;
1081         linkCount++; // Notify write check.
1082
1083         // GlobalLexicalVarWithVarInjectionsCheck
1084         linkCount++; // var injection check.
1085         if (needsTDZCheck)
1086             linkCount++;
1087         linkCount++; // Notify write check.
1088     }
1089     if (!linkCount)
1090         return;
1091     while (linkCount--)
1092         linkSlowCase(iter);
1093
1094     if (resolveType == ModuleVar) {
1095         JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_throw_strict_mode_readonly_property_write_error);
1096         slowPathCall.call();
1097     } else
1098         callOperation(operationPutToScope, currentInstruction);
1099 }
1100
1101 void JIT::emit_op_get_from_arguments(Instruction* currentInstruction)
1102 {
1103     int dst = currentInstruction[1].u.operand;
1104     int arguments = currentInstruction[2].u.operand;
1105     int index = currentInstruction[3].u.operand;
1106     
1107     emitLoadPayload(arguments, regT0);
1108     load32(Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + TagOffset), regT1);
1109     load32(Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + PayloadOffset), regT0);
1110     emitValueProfilingSite();
1111     emitStore(dst, regT1, regT0);
1112 }
1113
1114 void JIT::emit_op_put_to_arguments(Instruction* currentInstruction)
1115 {
1116     int arguments = currentInstruction[1].u.operand;
1117     int index = currentInstruction[2].u.operand;
1118     int value = currentInstruction[3].u.operand;
1119     
1120     emitWriteBarrier(arguments, value, ShouldFilterValue);
1121     
1122     emitLoadPayload(arguments, regT0);
1123     emitLoad(value, regT1, regT2);
1124     store32(regT1, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + TagOffset));
1125     store32(regT2, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + PayloadOffset));
1126 }
1127
1128 } // namespace JSC
1129
1130 #endif // USE(JSVALUE32_64)
1131 #endif // ENABLE(JIT)