Transition op_new_* JITStubs to JIT operations.
[WebKit-https.git] / Source / JavaScriptCore / jit / JITStubs.cpp
1 /*
2  * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4  * Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32
33 #if ENABLE(JIT)
34 #include "JITStubs.h"
35
36 #include "Arguments.h"
37 #include "ArrayConstructor.h"
38 #include "CallFrame.h"
39 #include "CallFrameInlines.h"
40 #include "CodeBlock.h"
41 #include "CodeProfiling.h"
42 #include "CommonSlowPaths.h"
43 #include "DFGCompilationMode.h"
44 #include "DFGDriver.h"
45 #include "DFGOSREntry.h"
46 #include "DFGWorklist.h"
47 #include "Debugger.h"
48 #include "DeferGC.h"
49 #include "ErrorInstance.h"
50 #include "ExceptionHelpers.h"
51 #include "GetterSetter.h"
52 #include "Heap.h"
53 #include <wtf/InlineASM.h>
54 #include "JIT.h"
55 #include "JITExceptions.h"
56 #include "JITToDFGDeferredCompilationCallback.h"
57 #include "JSActivation.h"
58 #include "JSArray.h"
59 #include "JSFunction.h"
60 #include "JSGlobalObjectFunctions.h"
61 #include "JSNameScope.h"
62 #include "JSNotAnObject.h"
63 #include "JSPropertyNameIterator.h"
64 #include "JSString.h"
65 #include "JSWithScope.h"
66 #include "LegacyProfiler.h"
67 #include "NameInstance.h"
68 #include "ObjectConstructor.h"
69 #include "ObjectPrototype.h"
70 #include "Operations.h"
71 #include "Parser.h"
72 #include "RegExpObject.h"
73 #include "RegExpPrototype.h"
74 #include "Register.h"
75 #include "RepatchBuffer.h"
76 #include "SamplingTool.h"
77 #include "SlowPathCall.h"
78 #include "Strong.h"
79 #include "StructureRareDataInlines.h"
80 #include <wtf/StdLibExtras.h>
81 #include <stdarg.h>
82 #include <stdio.h>
83
84 using namespace std;
85
86 #if CPU(ARM_TRADITIONAL)
87 #include "JITStubsARM.h"
88 #elif CPU(ARM_THUMB2)
89 #include "JITStubsARMv7.h"
90 #elif CPU(MIPS)
91 #include "JITStubsMIPS.h"
92 #elif CPU(SH4)
93 #include "JITStubsSH4.h"
94 #elif CPU(X86)
95 #include "JITStubsX86.h"
96 #elif CPU(X86_64)
97 #include "JITStubsX86_64.h"
98 #else
99 #error "JIT not supported on this platform."
100 #endif
101
102 namespace JSC {
103
104 #if ENABLE(OPCODE_SAMPLING)
105     #define CTI_SAMPLER stackFrame.vm->interpreter->sampler()
106 #else
107     #define CTI_SAMPLER 0
108 #endif
109
110 void performPlatformSpecificJITAssertions(VM* vm)
111 {
112     if (!vm->canUseJIT())
113         return;
114
115 #if CPU(ARM_THUMB2)
116     performARMv7JITAssertions();
117 #elif CPU(ARM_TRADITIONAL)
118     performARMJITAssertions();
119 #elif CPU(MIPS)
120     performMIPSJITAssertions();
121 #elif CPU(SH4)
122     performSH4JITAssertions();
123 #endif
124 }
125
126 NEVER_INLINE static void tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo, bool direct)
127 {
128     ConcurrentJITLocker locker(codeBlock->m_lock);
129     
130     // The interpreter checks for recursion here; I do not believe this can occur in CTI.
131
132     if (!baseValue.isCell())
133         return;
134
135     // Uncacheable: give up.
136     if (!slot.isCacheable()) {
137         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
138         return;
139     }
140     
141     JSCell* baseCell = baseValue.asCell();
142     Structure* structure = baseCell->structure();
143
144     if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
145         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
146         return;
147     }
148
149     // If baseCell != base, then baseCell must be a proxy for another object.
150     if (baseCell != slot.base()) {
151         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
152         return;
153     }
154
155     // Cache hit: Specialize instruction and ref Structures.
156
157     // Structure transition, cache transition info
158     if (slot.type() == PutPropertySlot::NewProperty) {
159         if (structure->isDictionary()) {
160             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
161             return;
162         }
163
164         // put_by_id_transition checks the prototype chain for setters.
165         if (normalizePrototypeChain(callFrame, baseCell) == InvalidPrototypeChain) {
166             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
167             return;
168         }
169
170         StructureChain* prototypeChain = structure->prototypeChain(callFrame);
171         ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
172         stubInfo->initPutByIdTransition(callFrame->vm(), codeBlock->ownerExecutable(), structure->previousID(), structure, prototypeChain, direct);
173         JIT::compilePutByIdTransition(callFrame->scope()->vm(), codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress, direct);
174         return;
175     }
176     
177     stubInfo->initPutByIdReplace(callFrame->vm(), codeBlock->ownerExecutable(), structure);
178
179     JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress, direct);
180 }
181
182 NEVER_INLINE static void tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo)
183 {
184     ConcurrentJITLocker locker(codeBlock->m_lock);
185     
186     // FIXME: Write a test that proves we need to check for recursion here just
187     // like the interpreter does, then add a check for recursion.
188
189     // FIXME: Cache property access for immediates.
190     if (!baseValue.isCell()) {
191         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
192         return;
193     }
194     
195     VM* vm = &callFrame->vm();
196
197     if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
198         JIT::compilePatchGetArrayLength(callFrame->scope()->vm(), codeBlock, returnAddress);
199         return;
200     }
201     
202     if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
203         // The tradeoff of compiling an patched inline string length access routine does not seem
204         // to pay off, so we currently only do this for arrays.
205         ctiPatchCallByReturnAddress(codeBlock, returnAddress, vm->getCTIStub(stringLengthTrampolineGenerator).code());
206         return;
207     }
208
209     // Uncacheable: give up.
210     if (!slot.isCacheable()) {
211         stubInfo->accessType = access_get_by_id_generic;
212         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
213         return;
214     }
215
216     JSCell* baseCell = baseValue.asCell();
217     Structure* structure = baseCell->structure();
218
219     if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
220         stubInfo->accessType = access_get_by_id_generic;
221         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
222         return;
223     }
224
225     // Cache hit: Specialize instruction and ref Structures.
226
227     if (slot.slotBase() == baseValue) {
228         RELEASE_ASSERT(stubInfo->accessType == access_unset);
229         if (!slot.isCacheableValue() || !MacroAssembler::isCompactPtrAlignedAddressOffset(maxOffsetRelativeToPatchedStorage(slot.cachedOffset())))
230             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
231         else {
232             JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
233             stubInfo->initGetByIdSelf(callFrame->vm(), codeBlock->ownerExecutable(), structure);
234         }
235         return;
236     }
237
238     if (structure->isDictionary()) {
239         stubInfo->accessType = access_get_by_id_generic;
240         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
241         return;
242     }
243
244     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
245         JSObject* slotBaseObject = asObject(slot.slotBase());
246         size_t offset = slot.cachedOffset();
247
248         if (structure->typeInfo().hasImpureGetOwnPropertySlot()) {
249             stubInfo->accessType = access_get_by_id_generic;
250             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
251             return;
252         }
253         
254         // Since we're accessing a prototype in a loop, it's a good bet that it
255         // should not be treated as a dictionary.
256         if (slotBaseObject->structure()->isDictionary()) {
257             slotBaseObject->flattenDictionaryObject(callFrame->vm());
258             offset = slotBaseObject->structure()->get(callFrame->vm(), propertyName);
259         }
260         
261         stubInfo->initGetByIdProto(callFrame->vm(), codeBlock->ownerExecutable(), structure, slotBaseObject->structure(), slot.isCacheableValue());
262
263         ASSERT(!structure->isDictionary());
264         ASSERT(!slotBaseObject->structure()->isDictionary());
265         JIT::compileGetByIdProto(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), propertyName, slot, offset, returnAddress);
266         return;
267     }
268
269     PropertyOffset offset = slot.cachedOffset();
270     size_t count = normalizePrototypeChainForChainAccess(callFrame, baseValue, slot.slotBase(), propertyName, offset);
271     if (count == InvalidPrototypeChain) {
272         stubInfo->accessType = access_get_by_id_generic;
273         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
274         return;
275     }
276
277     StructureChain* prototypeChain = structure->prototypeChain(callFrame);
278     stubInfo->initGetByIdChain(callFrame->vm(), codeBlock->ownerExecutable(), structure, prototypeChain, count, slot.isCacheableValue());
279     JIT::compileGetByIdChain(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
280 }
281
282 #if !defined(NDEBUG)
283
284 extern "C" {
285
286 static void jscGeneratedNativeCode() 
287 {
288     // When executing a JIT stub function (which might do an allocation), we hack the return address
289     // to pretend to be executing this function, to keep stack logging tools from blowing out
290     // memory.
291 }
292
293 }
294
295 struct StackHack {
296     ALWAYS_INLINE StackHack(JITStackFrame& stackFrame) 
297         : stackFrame(stackFrame)
298         , savedReturnAddress(*stackFrame.returnAddressSlot())
299     {
300         if (!CodeProfiling::enabled())
301             *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
302     }
303
304     ALWAYS_INLINE ~StackHack() 
305     { 
306         *stackFrame.returnAddressSlot() = savedReturnAddress;
307     }
308
309     JITStackFrame& stackFrame;
310     ReturnAddressPtr savedReturnAddress;
311 };
312
313 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
314 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
315 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
316
317 #else
318
319 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS)
320 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
321 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
322
323 #endif
324
325 // The reason this is not inlined is to avoid having to do a PIC branch
326 // to get the address of the ctiVMThrowTrampoline function. It's also
327 // good to keep the code size down by leaving as much of the exception
328 // handling code out of line as possible.
329 static NEVER_INLINE void returnToThrowTrampoline(VM* vm, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
330 {
331     RELEASE_ASSERT(vm->exception());
332     vm->exceptionLocation = exceptionLocation;
333     returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline));
334 }
335
336 #define VM_THROW_EXCEPTION() \
337     do { \
338         VM_THROW_EXCEPTION_AT_END(); \
339         return 0; \
340     } while (0)
341 #define VM_THROW_EXCEPTION_AT_END() \
342     do {\
343         returnToThrowTrampoline(stackFrame.vm, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS);\
344     } while (0)
345
346 #define CHECK_FOR_EXCEPTION() \
347     do { \
348         if (UNLIKELY(stackFrame.vm->exception())) \
349             VM_THROW_EXCEPTION(); \
350     } while (0)
351 #define CHECK_FOR_EXCEPTION_AT_END() \
352     do { \
353         if (UNLIKELY(stackFrame.vm->exception())) \
354             VM_THROW_EXCEPTION_AT_END(); \
355     } while (0)
356 #define CHECK_FOR_EXCEPTION_VOID() \
357     do { \
358         if (UNLIKELY(stackFrame.vm->exception())) { \
359             VM_THROW_EXCEPTION_AT_END(); \
360             return; \
361         } \
362     } while (0)
363
364 class ErrorFunctor {
365 public:
366     virtual ~ErrorFunctor() { }
367     virtual JSValue operator()(ExecState*) = 0;
368 };
369
370 class ErrorWithExecFunctor : public ErrorFunctor {
371 public:
372     typedef JSObject* (*Factory)(ExecState* exec);
373     
374     ErrorWithExecFunctor(Factory factory)
375         : m_factory(factory)
376     {
377     }
378
379     virtual JSValue operator()(ExecState* exec) OVERRIDE
380     {
381         return m_factory(exec);
382     }
383
384 private:
385     Factory m_factory;
386 };
387
388 class ErrorWithExecAndCalleeFunctor : public ErrorFunctor {
389 public:
390     typedef JSObject* (*Factory)(ExecState* exec, JSValue callee);
391
392     ErrorWithExecAndCalleeFunctor(Factory factory, JSValue callee)
393         : m_factory(factory), m_callee(callee)
394     {
395     }
396
397     virtual JSValue operator()(ExecState* exec) OVERRIDE
398     {
399         return m_factory(exec, m_callee);
400     }
401 private:
402     Factory m_factory;
403     JSValue m_callee;
404 };
405
406 // Helper function for JIT stubs that may throw an exception in the middle of
407 // processing a function call. This function rolls back the stack to
408 // our caller, so exception processing can proceed from a valid state.
409 template<typename T> static T throwExceptionFromOpCall(JITStackFrame& jitStackFrame, CallFrame* newCallFrame, ReturnAddressPtr& returnAddressSlot, ErrorFunctor* createError = 0)
410 {
411     CallFrame* callFrame = newCallFrame->callerFrame()->removeHostCallFrameFlag();
412     jitStackFrame.callFrame = callFrame;
413     ASSERT(callFrame);
414     callFrame->vm().topCallFrame = callFrame;
415     if (createError)
416         callFrame->vm().throwException(callFrame, (*createError)(callFrame));
417     ASSERT(callFrame->vm().exception());
418     returnToThrowTrampoline(&callFrame->vm(), ReturnAddressPtr(newCallFrame->returnPC()), returnAddressSlot);
419     return T();
420 }
421
422 // If the CPU specific header does not provide an implementation, use the default one here.
423 #ifndef DEFINE_STUB_FUNCTION
424 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
425 #endif
426
427 DEFINE_STUB_FUNCTION(void, handle_watchdog_timer)
428 {
429     STUB_INIT_STACK_FRAME(stackFrame);
430     CallFrame* callFrame = stackFrame.callFrame;
431     VM* vm = stackFrame.vm;
432     if (UNLIKELY(vm->watchdog.didFire(callFrame))) {
433         vm->throwException(callFrame, createTerminatedExecutionException(vm));
434         VM_THROW_EXCEPTION_AT_END();
435         return;
436     }
437 }
438
439 DEFINE_STUB_FUNCTION(void, op_put_by_id_generic)
440 {
441     STUB_INIT_STACK_FRAME(stackFrame);
442
443     PutPropertySlot slot(
444         stackFrame.callFrame->codeBlock()->isStrictMode(),
445         stackFrame.callFrame->codeBlock()->putByIdContext());
446     stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
447     CHECK_FOR_EXCEPTION_AT_END();
448 }
449
450 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
451 {
452     STUB_INIT_STACK_FRAME(stackFrame);
453     
454     PutPropertySlot slot(
455         stackFrame.callFrame->codeBlock()->isStrictMode(),
456         stackFrame.callFrame->codeBlock()->putByIdContext());
457     JSValue baseValue = stackFrame.args[0].jsValue();
458     ASSERT(baseValue.isObject());
459     asObject(baseValue)->putDirect(stackFrame.callFrame->vm(), stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
460     CHECK_FOR_EXCEPTION_AT_END();
461 }
462
463 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
464 {
465     STUB_INIT_STACK_FRAME(stackFrame);
466
467     CallFrame* callFrame = stackFrame.callFrame;
468     Identifier& ident = stackFrame.args[1].identifier();
469
470     JSValue baseValue = stackFrame.args[0].jsValue();
471     PropertySlot slot(baseValue);
472     JSValue result = baseValue.get(callFrame, ident, slot);
473
474     CHECK_FOR_EXCEPTION_AT_END();
475     return JSValue::encode(result);
476 }
477
478 DEFINE_STUB_FUNCTION(void, op_put_by_id)
479 {
480     STUB_INIT_STACK_FRAME(stackFrame);
481     CallFrame* callFrame = stackFrame.callFrame;
482     Identifier& ident = stackFrame.args[1].identifier();
483     
484     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
485     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
486     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
487
488     PutPropertySlot slot(
489         callFrame->codeBlock()->isStrictMode(),
490         callFrame->codeBlock()->putByIdContext());
491     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
492     
493     if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
494         stubInfo->setSeen();
495         tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false);
496     }
497     
498     CHECK_FOR_EXCEPTION_AT_END();
499 }
500
501 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
502 {
503     STUB_INIT_STACK_FRAME(stackFrame);
504     CallFrame* callFrame = stackFrame.callFrame;
505     Identifier& ident = stackFrame.args[1].identifier();
506     
507     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
508     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
509     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
510
511     PutPropertySlot slot(
512         callFrame->codeBlock()->isStrictMode(),
513         callFrame->codeBlock()->putByIdContext());
514     JSValue baseValue = stackFrame.args[0].jsValue();
515     ASSERT(baseValue.isObject());
516     
517     asObject(baseValue)->putDirect(callFrame->vm(), ident, stackFrame.args[2].jsValue(), slot);
518     
519     if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
520         stubInfo->setSeen();
521         tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true);
522     }
523     
524     CHECK_FOR_EXCEPTION_AT_END();
525 }
526
527 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
528 {
529     STUB_INIT_STACK_FRAME(stackFrame);
530
531     CallFrame* callFrame = stackFrame.callFrame;
532     Identifier& ident = stackFrame.args[1].identifier();
533     
534     PutPropertySlot slot(
535         callFrame->codeBlock()->isStrictMode(),
536         callFrame->codeBlock()->putByIdContext());
537     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
538
539     CHECK_FOR_EXCEPTION_AT_END();
540 }
541
542 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
543 {
544     STUB_INIT_STACK_FRAME(stackFrame);
545     
546     CallFrame* callFrame = stackFrame.callFrame;
547     Identifier& ident = stackFrame.args[1].identifier();
548     
549     PutPropertySlot slot(
550         callFrame->codeBlock()->isStrictMode(),
551         callFrame->codeBlock()->putByIdContext());
552     JSValue baseValue = stackFrame.args[0].jsValue();
553     ASSERT(baseValue.isObject());
554     asObject(baseValue)->putDirect(callFrame->vm(), ident, stackFrame.args[2].jsValue(), slot);
555     
556     CHECK_FOR_EXCEPTION_AT_END();
557 }
558
559 DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
560 {
561     STUB_INIT_STACK_FRAME(stackFrame);
562
563     JSValue baseValue = stackFrame.args[0].jsValue();
564     int32_t oldSize = stackFrame.args[3].int32();
565     Structure* newStructure = stackFrame.args[4].structure();
566     int32_t newSize = newStructure->outOfLineCapacity();
567     
568     ASSERT(oldSize >= 0);
569     ASSERT(newSize > oldSize);
570
571     ASSERT(baseValue.isObject());
572     JSObject* base = asObject(baseValue);
573     VM& vm = *stackFrame.vm;
574     Butterfly* butterfly = base->growOutOfLineStorage(vm, oldSize, newSize);
575     base->setStructureAndButterfly(vm, newStructure, butterfly);
576
577     return base;
578 }
579
580 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
581 {
582     STUB_INIT_STACK_FRAME(stackFrame);
583     CallFrame* callFrame = stackFrame.callFrame;
584     Identifier& ident = stackFrame.args[1].identifier();
585
586     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
587     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
588     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
589
590     JSValue baseValue = stackFrame.args[0].jsValue();
591     PropertySlot slot(baseValue);
592     JSValue result = baseValue.get(callFrame, ident, slot);
593     
594     if (accessType != static_cast<AccessType>(stubInfo->accessType))
595         return JSValue::encode(result);
596
597     if (!stubInfo->seenOnce())
598         stubInfo->setSeen();
599     else
600         tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo);
601
602     CHECK_FOR_EXCEPTION_AT_END();
603     return JSValue::encode(result);
604 }
605
606 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
607 {
608     STUB_INIT_STACK_FRAME(stackFrame);
609
610     CallFrame* callFrame = stackFrame.callFrame;
611     Identifier& ident = stackFrame.args[1].identifier();
612
613     CodeBlock* codeBlock = callFrame->codeBlock();
614     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
615     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
616
617     JSValue baseValue = stackFrame.args[0].jsValue();
618     PropertySlot slot(baseValue);
619     JSValue result = baseValue.get(callFrame, ident, slot);
620     
621     if (accessType != static_cast<AccessType>(stubInfo->accessType))
622         return JSValue::encode(result);
623
624     CHECK_FOR_EXCEPTION();
625
626     ConcurrentJITLocker locker(codeBlock->m_lock);
627     
628     if (baseValue.isCell()
629         && slot.isCacheable()
630         && !baseValue.asCell()->structure()->isUncacheableDictionary()
631         && slot.slotBase() == baseValue) {
632
633         PolymorphicAccessStructureList* polymorphicStructureList;
634         int listIndex = 1;
635
636         if (stubInfo->accessType == access_unset)
637             stubInfo->initGetByIdSelf(callFrame->vm(), codeBlock->ownerExecutable(), baseValue.asCell()->structure());
638
639         if (stubInfo->accessType == access_get_by_id_self) {
640             ASSERT(!stubInfo->stubRoutine);
641             polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->vm(), codeBlock->ownerExecutable(), 0, stubInfo->u.getByIdSelf.baseObjectStructure.get(), true);
642             stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
643         } else {
644             polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
645             listIndex = stubInfo->u.getByIdSelfList.listSize;
646         }
647         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
648             stubInfo->u.getByIdSelfList.listSize++;
649             JIT::compileGetByIdSelfList(callFrame->scope()->vm(), codeBlock, stubInfo, polymorphicStructureList, listIndex, baseValue.asCell()->structure(), ident, slot, slot.cachedOffset());
650
651             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
652                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
653         }
654     } else
655         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
656     return JSValue::encode(result);
657 }
658
659 static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(VM& vm, ScriptExecutable* owner, StructureStubInfo* stubInfo, int& listIndex)
660 {
661     PolymorphicAccessStructureList* prototypeStructureList = 0;
662     listIndex = 1;
663
664     switch (stubInfo->accessType) {
665     case access_get_by_id_proto:
666         prototypeStructureList = new PolymorphicAccessStructureList(vm, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get(), true);
667         stubInfo->stubRoutine.clear();
668         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
669         break;
670     case access_get_by_id_chain:
671         prototypeStructureList = new PolymorphicAccessStructureList(vm, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get(), true);
672         stubInfo->stubRoutine.clear();
673         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
674         break;
675     case access_get_by_id_proto_list:
676         prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
677         listIndex = stubInfo->u.getByIdProtoList.listSize;
678         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE)
679             stubInfo->u.getByIdProtoList.listSize++;
680         break;
681     default:
682         RELEASE_ASSERT_NOT_REACHED();
683     }
684     
685     ASSERT(listIndex <= POLYMORPHIC_LIST_CACHE_SIZE);
686     return prototypeStructureList;
687 }
688
689 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_getter_stub)
690 {
691     STUB_INIT_STACK_FRAME(stackFrame);
692     CallFrame* callFrame = stackFrame.callFrame;
693     JSValue result = callGetter(callFrame, stackFrame.args[1].jsObject(), stackFrame.args[0].jsObject());
694     if (callFrame->hadException())
695         returnToThrowTrampoline(&callFrame->vm(), stackFrame.args[2].returnAddress(), STUB_RETURN_ADDRESS);
696
697     return JSValue::encode(result);
698 }
699
700 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_custom_stub)
701 {
702     STUB_INIT_STACK_FRAME(stackFrame);
703     CallFrame* callFrame = stackFrame.callFrame;
704     JSObject* slotBase = stackFrame.args[0].jsObject();
705     PropertySlot::GetValueFunc getter = reinterpret_cast<PropertySlot::GetValueFunc>(stackFrame.args[1].asPointer);
706     const Identifier& ident = stackFrame.args[2].identifier();
707     JSValue result = getter(callFrame, slotBase, ident);
708     if (callFrame->hadException())
709         returnToThrowTrampoline(&callFrame->vm(), stackFrame.args[3].returnAddress(), STUB_RETURN_ADDRESS);
710     
711     return JSValue::encode(result);
712 }
713
714 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
715 {
716     STUB_INIT_STACK_FRAME(stackFrame);
717
718     CallFrame* callFrame = stackFrame.callFrame;
719     const Identifier& propertyName = stackFrame.args[1].identifier();
720
721     CodeBlock* codeBlock = callFrame->codeBlock();
722     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
723     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
724
725     JSValue baseValue = stackFrame.args[0].jsValue();
726     PropertySlot slot(baseValue);
727     JSValue result = baseValue.get(callFrame, propertyName, slot);
728
729     CHECK_FOR_EXCEPTION();
730
731     if (accessType != static_cast<AccessType>(stubInfo->accessType)
732         || !baseValue.isCell()
733         || !slot.isCacheable()
734         || baseValue.asCell()->structure()->isDictionary()
735         || baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()) {
736         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
737         return JSValue::encode(result);
738     }
739
740     ConcurrentJITLocker locker(codeBlock->m_lock);
741     
742     Structure* structure = baseValue.asCell()->structure();
743
744     JSObject* slotBaseObject = asObject(slot.slotBase());
745     
746     PropertyOffset offset = slot.cachedOffset();
747
748     if (slot.slotBase() == baseValue)
749         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
750     else if (slot.slotBase() == baseValue.asCell()->structure()->prototypeForLookup(callFrame)) {
751         ASSERT(!baseValue.asCell()->structure()->isDictionary());
752         
753         if (baseValue.asCell()->structure()->typeInfo().hasImpureGetOwnPropertySlot()) {
754             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
755             return JSValue::encode(result);
756         }
757         
758         // Since we're accessing a prototype in a loop, it's a good bet that it
759         // should not be treated as a dictionary.
760         if (slotBaseObject->structure()->isDictionary()) {
761             slotBaseObject->flattenDictionaryObject(callFrame->vm());
762             offset = slotBaseObject->structure()->get(callFrame->vm(), propertyName);
763         }
764
765         int listIndex;
766         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->vm(), codeBlock->ownerExecutable(), stubInfo, listIndex);
767         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
768             JIT::compileGetByIdProtoList(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset);
769
770             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
771                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
772         }
773     } else {
774         size_t count = normalizePrototypeChainForChainAccess(callFrame, baseValue, slot.slotBase(), propertyName, offset);
775         if (count == InvalidPrototypeChain) {
776             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
777             return JSValue::encode(result);
778         }
779         
780         ASSERT(!baseValue.asCell()->structure()->isDictionary());
781         int listIndex;
782         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->vm(), codeBlock->ownerExecutable(), stubInfo, listIndex);
783         
784         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
785             StructureChain* protoChain = structure->prototypeChain(callFrame);
786             JIT::compileGetByIdChainList(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, propertyName, slot, offset);
787
788             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
789                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
790         }
791     }
792
793     return JSValue::encode(result);
794 }
795
796 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list_full)
797 {
798     STUB_INIT_STACK_FRAME(stackFrame);
799
800     JSValue baseValue = stackFrame.args[0].jsValue();
801     PropertySlot slot(baseValue);
802     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
803
804     CHECK_FOR_EXCEPTION_AT_END();
805     return JSValue::encode(result);
806 }
807
808 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_fail)
809 {
810     STUB_INIT_STACK_FRAME(stackFrame);
811
812     JSValue baseValue = stackFrame.args[0].jsValue();
813     PropertySlot slot(baseValue);
814     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
815
816     CHECK_FOR_EXCEPTION_AT_END();
817     return JSValue::encode(result);
818 }
819
820 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_array_fail)
821 {
822     STUB_INIT_STACK_FRAME(stackFrame);
823
824     JSValue baseValue = stackFrame.args[0].jsValue();
825     PropertySlot slot(baseValue);
826     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
827
828     CHECK_FOR_EXCEPTION_AT_END();
829     return JSValue::encode(result);
830 }
831
832 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail)
833 {
834     STUB_INIT_STACK_FRAME(stackFrame);
835
836     JSValue baseValue = stackFrame.args[0].jsValue();
837     PropertySlot slot(baseValue);
838     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
839
840     CHECK_FOR_EXCEPTION_AT_END();
841     return JSValue::encode(result);
842 }
843
844 DEFINE_STUB_FUNCTION(EncodedJSValue, op_check_has_instance)
845 {
846     STUB_INIT_STACK_FRAME(stackFrame);
847
848     CallFrame* callFrame = stackFrame.callFrame;
849     JSValue value = stackFrame.args[0].jsValue();
850     JSValue baseVal = stackFrame.args[1].jsValue();
851
852     if (baseVal.isObject()) {
853         JSObject* baseObject = asObject(baseVal);
854         ASSERT(!baseObject->structure()->typeInfo().implementsDefaultHasInstance());
855         if (baseObject->structure()->typeInfo().implementsHasInstance()) {
856             bool result = baseObject->methodTable()->customHasInstance(baseObject, callFrame, value);
857             CHECK_FOR_EXCEPTION_AT_END();
858             return JSValue::encode(jsBoolean(result));
859         }
860     }
861
862     stackFrame.vm->throwException(callFrame, createInvalidParameterError(callFrame, "instanceof", baseVal));
863     VM_THROW_EXCEPTION_AT_END();
864     return JSValue::encode(JSValue());
865 }
866
867 #if ENABLE(DFG_JIT)
868 DEFINE_STUB_FUNCTION(void, optimize)
869 {
870     STUB_INIT_STACK_FRAME(stackFrame);
871     
872     // Defer GC so that it doesn't run between when we enter into this slow path and
873     // when we figure out the state of our code block. This prevents a number of
874     // awkward reentrancy scenarios, including:
875     //
876     // - The optimized version of our code block being jettisoned by GC right after
877     //   we concluded that we wanted to use it.
878     //
879     // - An optimized version of our code block being installed just as we decided
880     //   that it wasn't ready yet.
881     //
882     // This still leaves the following: anytime we return from cti_optimize, we may
883     // GC, and the GC may either jettison the optimized version of our code block,
884     // or it may install the optimized version of our code block even though we
885     // concluded that it wasn't ready yet.
886     //
887     // Note that jettisoning won't happen if we already initiated OSR, because in
888     // that case we would have already planted the optimized code block into the JS
889     // stack.
890     DeferGC deferGC(stackFrame.vm->heap);
891     
892     CallFrame* callFrame = stackFrame.callFrame;
893     CodeBlock* codeBlock = callFrame->codeBlock();
894     VM& vm = callFrame->vm();
895     unsigned bytecodeIndex = stackFrame.args[0].int32();
896
897     if (bytecodeIndex) {
898         // If we're attempting to OSR from a loop, assume that this should be
899         // separately optimized.
900         codeBlock->m_shouldAlwaysBeInlined = false;
901     }
902     
903     if (Options::verboseOSR()) {
904         dataLog(
905             *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex,
906             ", executeCounter = ", codeBlock->jitExecuteCounter(),
907             ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(),
908             ", exitCounter = ");
909         if (codeBlock->hasOptimizedReplacement())
910             dataLog(codeBlock->replacement()->osrExitCounter());
911         else
912             dataLog("N/A");
913         dataLog("\n");
914     }
915
916     if (!codeBlock->checkIfOptimizationThresholdReached()) {
917         codeBlock->updateAllPredictions();
918         if (Options::verboseOSR())
919             dataLog("Choosing not to optimize ", *codeBlock, " yet, because the threshold hasn't been reached.\n");
920         return;
921     }
922     
923     if (codeBlock->m_shouldAlwaysBeInlined) {
924         codeBlock->updateAllPredictions();
925         codeBlock->optimizeAfterWarmUp();
926         if (Options::verboseOSR())
927             dataLog("Choosing not to optimize ", *codeBlock, " yet, because m_shouldAlwaysBeInlined == true.\n");
928         return;
929     }
930     
931     // We cannot be in the process of asynchronous compilation and also have an optimized
932     // replacement.
933     ASSERT(
934         !vm.worklist
935         || !(vm.worklist->compilationState(DFG::CompilationKey(codeBlock, DFG::DFGMode)) != DFG::Worklist::NotKnown
936              && codeBlock->hasOptimizedReplacement()));
937     
938     DFG::Worklist::State worklistState;
939     if (vm.worklist) {
940         // The call to DFG::Worklist::completeAllReadyPlansForVM() will complete all ready
941         // (i.e. compiled) code blocks. But if it completes ours, we also need to know
942         // what the result was so that we don't plow ahead and attempt OSR or immediate
943         // reoptimization. This will have already also set the appropriate JIT execution
944         // count threshold depending on what happened, so if the compilation was anything
945         // but successful we just want to return early. See the case for worklistState ==
946         // DFG::Worklist::Compiled, below.
947         
948         // Note that we could have alternatively just called Worklist::compilationState()
949         // here, and if it returned Compiled, we could have then called
950         // completeAndScheduleOSR() below. But that would have meant that it could take
951         // longer for code blocks to be completed: they would only complete when *their*
952         // execution count trigger fired; but that could take a while since the firing is
953         // racy. It could also mean that code blocks that never run again after being
954         // compiled would sit on the worklist until next GC. That's fine, but it's
955         // probably a waste of memory. Our goal here is to complete code blocks as soon as
956         // possible in order to minimize the chances of us executing baseline code after
957         // optimized code is already available.
958         
959         worklistState = vm.worklist->completeAllReadyPlansForVM(
960             vm, DFG::CompilationKey(codeBlock, DFG::DFGMode));
961     } else
962         worklistState = DFG::Worklist::NotKnown;
963     
964     if (worklistState == DFG::Worklist::Compiling) {
965         // We cannot be in the process of asynchronous compilation and also have an optimized
966         // replacement.
967         RELEASE_ASSERT(!codeBlock->hasOptimizedReplacement());
968         codeBlock->setOptimizationThresholdBasedOnCompilationResult(CompilationDeferred);
969         return;
970     }
971     
972     if (worklistState == DFG::Worklist::Compiled) {
973         // If we don't have an optimized replacement but we did just get compiled, then
974         // the compilation failed or was invalidated, in which case the execution count
975         // thresholds have already been set appropriately by
976         // CodeBlock::setOptimizationThresholdBasedOnCompilationResult() and we have
977         // nothing left to do.
978         if (!codeBlock->hasOptimizedReplacement()) {
979             codeBlock->updateAllPredictions();
980             if (Options::verboseOSR())
981                 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
982             return;
983         }
984     } else if (codeBlock->hasOptimizedReplacement()) {
985         if (Options::verboseOSR())
986             dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
987         // If we have an optimized replacement, then it must be the case that we entered
988         // cti_optimize from a loop. That's because if there's an optimized replacement,
989         // then all calls to this function will be relinked to the replacement and so
990         // the prologue OSR will never fire.
991         
992         // This is an interesting threshold check. Consider that a function OSR exits
993         // in the middle of a loop, while having a relatively low exit count. The exit
994         // will reset the execution counter to some target threshold, meaning that this
995         // code won't be reached until that loop heats up for >=1000 executions. But then
996         // we do a second check here, to see if we should either reoptimize, or just
997         // attempt OSR entry. Hence it might even be correct for
998         // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
999         // additional checking anyway, to reduce the amount of recompilation thrashing.
1000         if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
1001             if (Options::verboseOSR()) {
1002                 dataLog(
1003                     "Triggering reoptimization of ", *codeBlock,
1004                     "(", *codeBlock->replacement(), ") (in loop).\n");
1005             }
1006             codeBlock->reoptimize();
1007             return;
1008         }
1009     } else {
1010         if (!codeBlock->shouldOptimizeNow()) {
1011             if (Options::verboseOSR()) {
1012                 dataLog(
1013                     "Delaying optimization for ", *codeBlock,
1014                     " because of insufficient profiling.\n");
1015             }
1016             return;
1017         }
1018         
1019         if (Options::verboseOSR())
1020             dataLog("Triggering optimized compilation of ", *codeBlock, "\n");
1021         
1022         unsigned numVarsWithValues;
1023         if (bytecodeIndex)
1024             numVarsWithValues = codeBlock->m_numVars;
1025         else
1026             numVarsWithValues = 0;
1027         Operands<JSValue> mustHandleValues(
1028             codeBlock->numParameters(), numVarsWithValues);
1029         for (size_t i = 0; i < mustHandleValues.size(); ++i) {
1030             int operand = mustHandleValues.operandForIndex(i);
1031             if (operandIsArgument(operand)
1032                 && !VirtualRegister(operand).toArgument()
1033                 && codeBlock->codeType() == FunctionCode
1034                 && codeBlock->specializationKind() == CodeForConstruct) {
1035                 // Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will
1036                 // also never be used. It doesn't matter what we put into the value for this,
1037                 // but it has to be an actual value that can be grokked by subsequent DFG passes,
1038                 // so we sanitize it here by turning it into Undefined.
1039                 mustHandleValues[i] = jsUndefined();
1040             } else
1041                 mustHandleValues[i] = callFrame->uncheckedR(operand).jsValue();
1042         }
1043         
1044         CompilationResult result = DFG::compile(
1045             vm, codeBlock->newReplacement().get(), DFG::DFGMode, bytecodeIndex,
1046             mustHandleValues, JITToDFGDeferredCompilationCallback::create(),
1047             vm.ensureWorklist());
1048         
1049         if (result != CompilationSuccessful)
1050             return;
1051     }
1052     
1053     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1054     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1055     
1056     if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) {
1057         if (Options::verboseOSR()) {
1058             dataLog(
1059                 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ", address ",
1060                 RawPointer((STUB_RETURN_ADDRESS).value()), " -> ", RawPointer(address), ".\n");
1061         }
1062
1063         codeBlock->optimizeSoon();
1064         STUB_SET_RETURN_ADDRESS(address);
1065         return;
1066     }
1067
1068     if (Options::verboseOSR()) {
1069         dataLog(
1070             "Optimizing ", *codeBlock, " -> ", *codeBlock->replacement(),
1071             " succeeded, OSR failed, after a delay of ",
1072             codeBlock->optimizationDelayCounter(), ".\n");
1073     }
1074
1075     // Count the OSR failure as a speculation failure. If this happens a lot, then
1076     // reoptimize.
1077     optimizedCodeBlock->countOSRExit();
1078     
1079     // We are a lot more conservative about triggering reoptimization after OSR failure than
1080     // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
1081     // already, then we really would like to reoptimize immediately. But this case covers
1082     // something else: there weren't many (or any) speculation failures before, but we just
1083     // failed to enter the speculative code because some variable had the wrong value or
1084     // because the OSR code decided for any spurious reason that it did not want to OSR
1085     // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
1086     // reoptimization trigger.
1087     if (optimizedCodeBlock->shouldReoptimizeNow()) {
1088         if (Options::verboseOSR()) {
1089             dataLog(
1090                 "Triggering reoptimization of ", *codeBlock, " -> ",
1091                 *codeBlock->replacement(), " (after OSR fail).\n");
1092         }
1093         codeBlock->reoptimize();
1094         return;
1095     }
1096
1097     // OSR failed this time, but it might succeed next time! Let the code run a bit
1098     // longer and then try again.
1099     codeBlock->optimizeAfterWarmUp();
1100 }
1101 #endif // ENABLE(DFG_JIT)
1102
1103 DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
1104 {
1105     STUB_INIT_STACK_FRAME(stackFrame);
1106
1107     CallFrame* callFrame = stackFrame.callFrame;
1108     JSValue value = stackFrame.args[0].jsValue();
1109     JSValue proto = stackFrame.args[1].jsValue();
1110     
1111     ASSERT(!value.isObject() || !proto.isObject());
1112
1113     bool result = JSObject::defaultHasInstance(callFrame, value, proto);
1114     CHECK_FOR_EXCEPTION_AT_END();
1115     return JSValue::encode(jsBoolean(result));
1116 }
1117
1118 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
1119 {
1120     STUB_INIT_STACK_FRAME(stackFrame);
1121
1122     CallFrame* callFrame = stackFrame.callFrame;
1123     
1124     JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
1125
1126     bool couldDelete = baseObj->methodTable()->deleteProperty(baseObj, callFrame, stackFrame.args[1].identifier());
1127     JSValue result = jsBoolean(couldDelete);
1128     if (!couldDelete && callFrame->codeBlock()->isStrictMode())
1129         stackFrame.vm->throwException(stackFrame.callFrame, createTypeError(stackFrame.callFrame, "Unable to delete property."));
1130
1131     CHECK_FOR_EXCEPTION_AT_END();
1132     return JSValue::encode(result);
1133 }
1134
1135 DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
1136 {
1137     STUB_INIT_STACK_FRAME(stackFrame);
1138
1139     JSActivation* activation = JSActivation::create(stackFrame.callFrame->vm(), stackFrame.callFrame, stackFrame.callFrame->codeBlock());
1140     stackFrame.callFrame->setScope(activation);
1141     return activation;
1142 }
1143
1144 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments)
1145 {
1146     STUB_INIT_STACK_FRAME(stackFrame);
1147
1148     Arguments* arguments = Arguments::create(*stackFrame.vm, stackFrame.callFrame);
1149     return JSValue::encode(JSValue(arguments));
1150 }
1151
1152 DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
1153 {
1154     STUB_INIT_STACK_FRAME(stackFrame);
1155
1156     ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
1157     jsCast<JSActivation*>(stackFrame.args[0].jsValue())->tearOff(*stackFrame.vm);
1158 }
1159
1160 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
1161 {
1162     STUB_INIT_STACK_FRAME(stackFrame);
1163
1164     CallFrame* callFrame = stackFrame.callFrame;
1165     ASSERT(callFrame->codeBlock()->usesArguments());
1166     Arguments* arguments = jsCast<Arguments*>(stackFrame.args[0].jsValue());
1167     if (JSValue activationValue = stackFrame.args[1].jsValue()) {
1168         arguments->didTearOffActivation(callFrame, jsCast<JSActivation*>(activationValue));
1169         return;
1170     }
1171     arguments->tearOff(callFrame);
1172 }
1173
1174 DEFINE_STUB_FUNCTION(void, op_profile_will_call)
1175 {
1176     STUB_INIT_STACK_FRAME(stackFrame);
1177
1178     if (LegacyProfiler* profiler = stackFrame.vm->enabledProfiler())
1179         profiler->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
1180 }
1181
1182 DEFINE_STUB_FUNCTION(void, op_profile_did_call)
1183 {
1184     STUB_INIT_STACK_FRAME(stackFrame);
1185
1186     if (LegacyProfiler* profiler = stackFrame.vm->enabledProfiler())
1187         profiler->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
1188 }
1189
1190 static JSValue getByVal(
1191     CallFrame* callFrame, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress)
1192 {
1193     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1194         if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame)))
1195             return result;
1196     }
1197
1198     if (subscript.isUInt32()) {
1199         uint32_t i = subscript.asUInt32();
1200         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
1201             ctiPatchCallByReturnAddress(callFrame->codeBlock(), returnAddress, FunctionPtr(cti_op_get_by_val_string));
1202             return asString(baseValue)->getIndex(callFrame, i);
1203         }
1204         return baseValue.get(callFrame, i);
1205     }
1206
1207     if (isName(subscript))
1208         return baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName());
1209
1210     Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1211     return baseValue.get(callFrame, property);
1212 }
1213
1214 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
1215 {
1216     STUB_INIT_STACK_FRAME(stackFrame);
1217
1218     CallFrame* callFrame = stackFrame.callFrame;
1219
1220     JSValue baseValue = stackFrame.args[0].jsValue();
1221     JSValue subscript = stackFrame.args[1].jsValue();
1222     
1223     if (baseValue.isObject() && subscript.isInt32()) {
1224         // See if it's worth optimizing this at all.
1225         JSObject* object = asObject(baseValue);
1226         bool didOptimize = false;
1227
1228         unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
1229         ASSERT(bytecodeOffset);
1230         ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
1231         ASSERT(!byValInfo.stubRoutine);
1232         
1233         if (hasOptimizableIndexing(object->structure())) {
1234             // Attempt to optimize.
1235             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure());
1236             if (arrayMode != byValInfo.arrayMode) {
1237                 JIT::compileGetByVal(&callFrame->vm(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode);
1238                 didOptimize = true;
1239             }
1240         }
1241         
1242         if (!didOptimize) {
1243             // If we take slow path more than 10 times without patching then make sure we
1244             // never make that mistake again. Or, if we failed to patch and we have some object
1245             // that intercepts indexed get, then don't even wait until 10 times. For cases
1246             // where we see non-index-intercepting objects, this gives 10 iterations worth of
1247             // opportunity for us to observe that the get_by_val may be polymorphic.
1248             if (++byValInfo.slowPathCount >= 10
1249                 || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1250                 // Don't ever try to optimize.
1251                 RepatchBuffer repatchBuffer(callFrame->codeBlock());
1252                 repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_generic));
1253             }
1254         }
1255     }
1256     
1257     JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS);
1258     CHECK_FOR_EXCEPTION();
1259     return JSValue::encode(result);
1260 }
1261     
1262 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_generic)
1263 {
1264     STUB_INIT_STACK_FRAME(stackFrame);
1265
1266     CallFrame* callFrame = stackFrame.callFrame;
1267
1268     JSValue baseValue = stackFrame.args[0].jsValue();
1269     JSValue subscript = stackFrame.args[1].jsValue();
1270     
1271     JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS);
1272     CHECK_FOR_EXCEPTION();
1273     return JSValue::encode(result);
1274 }
1275     
1276 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
1277 {
1278     STUB_INIT_STACK_FRAME(stackFrame);
1279     
1280     CallFrame* callFrame = stackFrame.callFrame;
1281     
1282     JSValue baseValue = stackFrame.args[0].jsValue();
1283     JSValue subscript = stackFrame.args[1].jsValue();
1284     
1285     JSValue result;
1286     
1287     if (LIKELY(subscript.isUInt32())) {
1288         uint32_t i = subscript.asUInt32();
1289         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1290             result = asString(baseValue)->getIndex(callFrame, i);
1291         else {
1292             result = baseValue.get(callFrame, i);
1293             if (!isJSString(baseValue))
1294                 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
1295         }
1296     } else if (isName(subscript))
1297         result = baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName());
1298     else {
1299         Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1300         result = baseValue.get(callFrame, property);
1301     }
1302     
1303     CHECK_FOR_EXCEPTION_AT_END();
1304     return JSValue::encode(result);
1305 }
1306
1307 static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value)
1308 {
1309     if (LIKELY(subscript.isUInt32())) {
1310         uint32_t i = subscript.asUInt32();
1311         if (baseValue.isObject()) {
1312             JSObject* object = asObject(baseValue);
1313             if (object->canSetIndexQuickly(i))
1314                 object->setIndexQuickly(callFrame->vm(), i, value);
1315             else
1316                 object->methodTable()->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
1317         } else
1318             baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
1319     } else if (isName(subscript)) {
1320         PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1321         baseValue.put(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
1322     } else {
1323         Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1324         if (!callFrame->vm().exception()) { // Don't put to an object if toString threw an exception.
1325             PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1326             baseValue.put(callFrame, property, value, slot);
1327         }
1328     }
1329 }
1330
1331 DEFINE_STUB_FUNCTION(void, op_put_by_val)
1332 {
1333     STUB_INIT_STACK_FRAME(stackFrame);
1334
1335     CallFrame* callFrame = stackFrame.callFrame;
1336
1337     JSValue baseValue = stackFrame.args[0].jsValue();
1338     JSValue subscript = stackFrame.args[1].jsValue();
1339     JSValue value = stackFrame.args[2].jsValue();
1340     
1341     if (baseValue.isObject() && subscript.isInt32()) {
1342         // See if it's worth optimizing at all.
1343         JSObject* object = asObject(baseValue);
1344         bool didOptimize = false;
1345
1346         unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
1347         ASSERT(bytecodeOffset);
1348         ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
1349         ASSERT(!byValInfo.stubRoutine);
1350         
1351         if (hasOptimizableIndexing(object->structure())) {
1352             // Attempt to optimize.
1353             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure());
1354             if (arrayMode != byValInfo.arrayMode) {
1355                 JIT::compilePutByVal(&callFrame->vm(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode);
1356                 didOptimize = true;
1357             }
1358         }
1359
1360         if (!didOptimize) {
1361             // If we take slow path more than 10 times without patching then make sure we
1362             // never make that mistake again. Or, if we failed to patch and we have some object
1363             // that intercepts indexed get, then don't even wait until 10 times. For cases
1364             // where we see non-index-intercepting objects, this gives 10 iterations worth of
1365             // opportunity for us to observe that the get_by_val may be polymorphic.
1366             if (++byValInfo.slowPathCount >= 10
1367                 || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1368                 // Don't ever try to optimize.
1369                 RepatchBuffer repatchBuffer(callFrame->codeBlock());
1370                 repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_generic));
1371             }
1372         }
1373     }
1374     
1375     putByVal(callFrame, baseValue, subscript, value);
1376
1377     CHECK_FOR_EXCEPTION_AT_END();
1378 }
1379
1380 DEFINE_STUB_FUNCTION(void, op_put_by_val_generic)
1381 {
1382     STUB_INIT_STACK_FRAME(stackFrame);
1383
1384     CallFrame* callFrame = stackFrame.callFrame;
1385
1386     JSValue baseValue = stackFrame.args[0].jsValue();
1387     JSValue subscript = stackFrame.args[1].jsValue();
1388     JSValue value = stackFrame.args[2].jsValue();
1389     
1390     putByVal(callFrame, baseValue, subscript, value);
1391
1392     CHECK_FOR_EXCEPTION_AT_END();
1393 }
1394
1395 DEFINE_STUB_FUNCTION(void*, op_load_varargs)
1396 {
1397     STUB_INIT_STACK_FRAME(stackFrame);
1398
1399     CallFrame* callFrame = stackFrame.callFrame;
1400     JSStack* stack = stackFrame.stack;
1401     JSValue thisValue = stackFrame.args[0].jsValue();
1402     JSValue arguments = stackFrame.args[1].jsValue();
1403     int firstFreeRegister = stackFrame.args[2].int32();
1404
1405     CallFrame* newCallFrame = loadVarargs(callFrame, stack, thisValue, arguments, firstFreeRegister);
1406     if (!newCallFrame)
1407         VM_THROW_EXCEPTION();
1408     return newCallFrame;
1409 }
1410
1411 DEFINE_STUB_FUNCTION(void*, op_throw)
1412 {
1413     STUB_INIT_STACK_FRAME(stackFrame);
1414     stackFrame.vm->throwException(stackFrame.callFrame, stackFrame.args[0].jsValue()); 
1415     ExceptionHandler handler = genericUnwind(stackFrame.vm, stackFrame.callFrame, stackFrame.args[0].jsValue());
1416     STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1417     return handler.callFrame;
1418 }
1419
1420 DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
1421 {
1422     STUB_INIT_STACK_FRAME(stackFrame);
1423
1424     CallFrame* callFrame = stackFrame.callFrame;
1425     JSObject* o = stackFrame.args[0].jsObject();
1426     Structure* structure = o->structure();
1427     JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
1428     if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
1429         jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
1430     return jsPropertyNameIterator;
1431 }
1432
1433 DEFINE_STUB_FUNCTION(void, op_push_with_scope)
1434 {
1435     STUB_INIT_STACK_FRAME(stackFrame);
1436
1437     JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame);
1438     CHECK_FOR_EXCEPTION_VOID();
1439     stackFrame.callFrame->setScope(JSWithScope::create(stackFrame.callFrame, o));
1440 }
1441
1442 DEFINE_STUB_FUNCTION(void, op_pop_scope)
1443 {
1444     STUB_INIT_STACK_FRAME(stackFrame);
1445
1446     stackFrame.callFrame->setScope(stackFrame.callFrame->scope()->next());
1447 }
1448
1449 DEFINE_STUB_FUNCTION(void, op_push_name_scope)
1450 {
1451     STUB_INIT_STACK_FRAME(stackFrame);
1452
1453     JSNameScope* scope = JSNameScope::create(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), stackFrame.args[2].int32());
1454
1455     CallFrame* callFrame = stackFrame.callFrame;
1456     callFrame->setScope(scope);
1457 }
1458
1459 DEFINE_STUB_FUNCTION(void, op_put_by_index)
1460 {
1461     STUB_INIT_STACK_FRAME(stackFrame);
1462
1463     CallFrame* callFrame = stackFrame.callFrame;
1464     unsigned property = stackFrame.args[1].int32();
1465
1466     JSValue arrayValue = stackFrame.args[0].jsValue();
1467     ASSERT(isJSArray(arrayValue));
1468     asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue());
1469 }
1470
1471 DEFINE_STUB_FUNCTION(void*, op_switch_imm)
1472 {
1473     STUB_INIT_STACK_FRAME(stackFrame);
1474
1475     JSValue scrutinee = stackFrame.args[0].jsValue();
1476     unsigned tableIndex = stackFrame.args[1].int32();
1477     CallFrame* callFrame = stackFrame.callFrame;
1478     CodeBlock* codeBlock = callFrame->codeBlock();
1479
1480     if (scrutinee.isInt32())
1481         return codeBlock->switchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress();
1482     if (scrutinee.isDouble() && scrutinee.asDouble() == static_cast<int32_t>(scrutinee.asDouble()))
1483         return codeBlock->switchJumpTable(tableIndex).ctiForValue(static_cast<int32_t>(scrutinee.asDouble())).executableAddress();
1484     return codeBlock->switchJumpTable(tableIndex).ctiDefault.executableAddress();
1485 }
1486
1487 DEFINE_STUB_FUNCTION(void*, op_switch_char)
1488 {
1489     STUB_INIT_STACK_FRAME(stackFrame);
1490
1491     JSValue scrutinee = stackFrame.args[0].jsValue();
1492     unsigned tableIndex = stackFrame.args[1].int32();
1493     CallFrame* callFrame = stackFrame.callFrame;
1494     CodeBlock* codeBlock = callFrame->codeBlock();
1495
1496     void* result = codeBlock->switchJumpTable(tableIndex).ctiDefault.executableAddress();
1497
1498     if (scrutinee.isString()) {
1499         StringImpl* value = asString(scrutinee)->value(callFrame).impl();
1500         if (value->length() == 1)
1501             result = codeBlock->switchJumpTable(tableIndex).ctiForValue((*value)[0]).executableAddress();
1502     }
1503
1504     CHECK_FOR_EXCEPTION_AT_END();
1505     return result;
1506 }
1507
1508 DEFINE_STUB_FUNCTION(void*, op_switch_string)
1509 {
1510     STUB_INIT_STACK_FRAME(stackFrame);
1511
1512     JSValue scrutinee = stackFrame.args[0].jsValue();
1513     unsigned tableIndex = stackFrame.args[1].int32();
1514     CallFrame* callFrame = stackFrame.callFrame;
1515     CodeBlock* codeBlock = callFrame->codeBlock();
1516
1517     void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
1518
1519     if (scrutinee.isString()) {
1520         StringImpl* value = asString(scrutinee)->value(callFrame).impl();
1521         result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
1522     }
1523
1524     CHECK_FOR_EXCEPTION_AT_END();
1525     return result;
1526 }
1527
1528 DEFINE_STUB_FUNCTION(void, op_put_getter_setter)
1529 {
1530     STUB_INIT_STACK_FRAME(stackFrame);
1531
1532     CallFrame* callFrame = stackFrame.callFrame;
1533
1534     ASSERT(stackFrame.args[0].jsValue().isObject());
1535     JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
1536
1537     VM& vm = callFrame->vm();
1538     GetterSetter* accessor = GetterSetter::create(vm);
1539
1540     JSValue getter = stackFrame.args[2].jsValue();
1541     JSValue setter = stackFrame.args[3].jsValue();
1542     ASSERT(getter.isObject() || getter.isUndefined());
1543     ASSERT(setter.isObject() || setter.isUndefined());
1544     ASSERT(getter.isObject() || setter.isObject());
1545
1546     if (!getter.isUndefined())
1547         accessor->setGetter(vm, asObject(getter));
1548     if (!setter.isUndefined())
1549         accessor->setSetter(vm, asObject(setter));
1550     baseObj->putDirectAccessor(callFrame, stackFrame.args[1].identifier(), accessor, Accessor);
1551 }
1552
1553 DEFINE_STUB_FUNCTION(void, op_throw_static_error)
1554 {
1555     STUB_INIT_STACK_FRAME(stackFrame);
1556
1557     CallFrame* callFrame = stackFrame.callFrame;
1558     String message = errorDescriptionForValue(callFrame, stackFrame.args[0].jsValue())->value(callFrame);
1559     if (stackFrame.args[1].asInt32)
1560         stackFrame.vm->throwException(callFrame, createReferenceError(callFrame, message));
1561     else
1562         stackFrame.vm->throwException(callFrame, createTypeError(callFrame, message));
1563     VM_THROW_EXCEPTION_AT_END();
1564 }
1565
1566 DEFINE_STUB_FUNCTION(void, op_debug)
1567 {
1568     STUB_INIT_STACK_FRAME(stackFrame);
1569
1570     CallFrame* callFrame = stackFrame.callFrame;
1571
1572     int debugHookID = stackFrame.args[0].int32();
1573     stackFrame.vm->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID));
1574 }
1575
1576 DEFINE_STUB_FUNCTION(void*, vm_throw)
1577 {
1578     STUB_INIT_STACK_FRAME(stackFrame);
1579     VM* vm = stackFrame.vm;
1580     ExceptionHandler handler = genericUnwind(vm, stackFrame.callFrame, vm->exception());
1581     STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1582     return handler.callFrame;
1583 }
1584
1585 #if USE(JSVALUE32_64)
1586 EncodedExceptionHandler JIT_STUB cti_vm_handle_exception(CallFrame* callFrame)
1587 {
1588     ASSERT(!callFrame->hasHostCallFrameFlag());
1589     if (!callFrame) {
1590         // The entire stack has already been unwound. Nothing more to handle.
1591         return encode(uncaughtExceptionHandler());
1592     }
1593
1594     VM* vm = callFrame->codeBlock()->vm();
1595     vm->topCallFrame = callFrame;
1596     return encode(genericUnwind(vm, callFrame, vm->exception()));
1597 }
1598 #else
1599 ExceptionHandler JIT_STUB cti_vm_handle_exception(CallFrame* callFrame)
1600 {
1601     ASSERT(!callFrame->hasHostCallFrameFlag());
1602     if (!callFrame) {
1603         // The entire stack has already been unwound. Nothing more to handle.
1604         return uncaughtExceptionHandler();
1605     }
1606
1607     VM* vm = callFrame->codeBlock()->vm();
1608     vm->topCallFrame = callFrame;
1609     return genericUnwind(vm, callFrame, vm->exception());
1610 }
1611 #endif
1612
1613 DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
1614 {
1615     STUB_INIT_STACK_FRAME(stackFrame);
1616
1617     CallFrame* callFrame = stackFrame.callFrame;
1618     return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
1619 }
1620
1621 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_scope)
1622 {
1623     STUB_INIT_STACK_FRAME(stackFrame);
1624     ExecState* exec = stackFrame.callFrame;
1625     Instruction* pc = stackFrame.args[0].pc();
1626
1627     const Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
1628     return JSValue::encode(JSScope::resolve(exec, exec->scope(), ident));
1629 }
1630
1631 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_from_scope)
1632 {
1633     STUB_INIT_STACK_FRAME(stackFrame);
1634     ExecState* exec = stackFrame.callFrame;
1635     Instruction* pc = stackFrame.args[0].pc();
1636
1637     const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
1638     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[2].u.operand).jsValue());
1639     ResolveModeAndType modeAndType(pc[4].u.operand);
1640
1641     PropertySlot slot(scope);
1642     if (!scope->getPropertySlot(exec, ident, slot)) {
1643         if (modeAndType.mode() == ThrowIfNotFound) {
1644             exec->vm().throwException(exec, createUndefinedVariableError(exec, ident));
1645             VM_THROW_EXCEPTION();
1646         }
1647         return JSValue::encode(jsUndefined());
1648     }
1649
1650     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
1651     if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure()->propertyAccessesAreCacheable()) {
1652         if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
1653             CodeBlock* codeBlock = exec->codeBlock();
1654             ConcurrentJITLocker locker(codeBlock->m_lock);
1655             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
1656             pc[6].u.operand = slot.cachedOffset();
1657         }
1658     }
1659
1660     return JSValue::encode(slot.getValue(exec, ident));
1661 }
1662
1663 DEFINE_STUB_FUNCTION(void, op_put_to_scope)
1664 {
1665     STUB_INIT_STACK_FRAME(stackFrame);
1666     ExecState* exec = stackFrame.callFrame;
1667     Instruction* pc = stackFrame.args[0].pc();
1668
1669     CodeBlock* codeBlock = exec->codeBlock();
1670     const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
1671     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[1].u.operand).jsValue());
1672     JSValue value = exec->r(pc[3].u.operand).jsValue();
1673     ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
1674
1675     if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident)) {
1676         exec->vm().throwException(exec, createUndefinedVariableError(exec, ident));
1677         VM_THROW_EXCEPTION_AT_END();
1678         return;
1679     }
1680
1681     PutPropertySlot slot(codeBlock->isStrictMode());
1682     scope->methodTable()->put(scope, exec, ident, value, slot);
1683     
1684     if (exec->vm().exception()) {
1685         VM_THROW_EXCEPTION_AT_END();
1686         return;
1687     }
1688
1689     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
1690     if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
1691         if (slot.isCacheable() && slot.base() == scope && scope->structure()->propertyAccessesAreCacheable()) {
1692             ConcurrentJITLocker locker(codeBlock->m_lock);
1693             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
1694             pc[6].u.operand = slot.cachedOffset();
1695         }
1696     }
1697 }
1698
1699 } // namespace JSC
1700
1701 #endif // ENABLE(JIT)