CodeBlock::prepareForExecution() is silly
[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 "DFGDriver.h"
44 #include "DFGOSREntry.h"
45 #include "DFGWorklist.h"
46 #include "Debugger.h"
47 #include "DeferGC.h"
48 #include "ErrorInstance.h"
49 #include "ExceptionHelpers.h"
50 #include "GetterSetter.h"
51 #include "Heap.h"
52 #include <wtf/InlineASM.h>
53 #include "JIT.h"
54 #include "JITExceptions.h"
55 #include "JITToDFGDeferredCompilationCallback.h"
56 #include "JSActivation.h"
57 #include "JSArray.h"
58 #include "JSFunction.h"
59 #include "JSGlobalObjectFunctions.h"
60 #include "JSNameScope.h"
61 #include "JSNotAnObject.h"
62 #include "JSPropertyNameIterator.h"
63 #include "JSString.h"
64 #include "JSWithScope.h"
65 #include "LegacyProfiler.h"
66 #include "NameInstance.h"
67 #include "ObjectConstructor.h"
68 #include "ObjectPrototype.h"
69 #include "Operations.h"
70 #include "Parser.h"
71 #include "RegExpObject.h"
72 #include "RegExpPrototype.h"
73 #include "Register.h"
74 #include "RepatchBuffer.h"
75 #include "SamplingTool.h"
76 #include "SlowPathCall.h"
77 #include "Strong.h"
78 #include "StructureRareDataInlines.h"
79 #include <wtf/StdLibExtras.h>
80 #include <stdarg.h>
81 #include <stdio.h>
82
83 using namespace std;
84
85 #if CPU(ARM_TRADITIONAL)
86 #include "JITStubsARM.h"
87 #elif CPU(ARM_THUMB2)
88 #include "JITStubsARMv7.h"
89 #elif CPU(MIPS)
90 #include "JITStubsMIPS.h"
91 #elif CPU(SH4)
92 #include "JITStubsSH4.h"
93 #elif CPU(X86)
94 #include "JITStubsX86.h"
95 #elif CPU(X86_64)
96 #include "JITStubsX86_64.h"
97 #else
98 #error "JIT not supported on this platform."
99 #endif
100
101 namespace JSC {
102
103 #if ENABLE(OPCODE_SAMPLING)
104     #define CTI_SAMPLER stackFrame.vm->interpreter->sampler()
105 #else
106     #define CTI_SAMPLER 0
107 #endif
108
109 void performPlatformSpecificJITAssertions(VM* vm)
110 {
111     if (!vm->canUseJIT())
112         return;
113
114 #if CPU(ARM_THUMB2)
115     performARMv7JITAssertions();
116 #elif CPU(ARM_TRADITIONAL)
117     performARMJITAssertions();
118 #elif CPU(MIPS)
119     performMIPSJITAssertions();
120 #elif CPU(SH4)
121     performSH4JITAssertions();
122 #endif
123 }
124
125 NEVER_INLINE static void tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo, bool direct)
126 {
127     ConcurrentJITLocker locker(codeBlock->m_lock);
128     
129     // The interpreter checks for recursion here; I do not believe this can occur in CTI.
130
131     if (!baseValue.isCell())
132         return;
133
134     // Uncacheable: give up.
135     if (!slot.isCacheable()) {
136         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
137         return;
138     }
139     
140     JSCell* baseCell = baseValue.asCell();
141     Structure* structure = baseCell->structure();
142
143     if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
144         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
145         return;
146     }
147
148     // If baseCell != base, then baseCell must be a proxy for another object.
149     if (baseCell != slot.base()) {
150         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
151         return;
152     }
153
154     // Cache hit: Specialize instruction and ref Structures.
155
156     // Structure transition, cache transition info
157     if (slot.type() == PutPropertySlot::NewProperty) {
158         if (structure->isDictionary()) {
159             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
160             return;
161         }
162
163         // put_by_id_transition checks the prototype chain for setters.
164         if (normalizePrototypeChain(callFrame, baseCell) == InvalidPrototypeChain) {
165             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
166             return;
167         }
168
169         StructureChain* prototypeChain = structure->prototypeChain(callFrame);
170         ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
171         stubInfo->initPutByIdTransition(callFrame->vm(), codeBlock->ownerExecutable(), structure->previousID(), structure, prototypeChain, direct);
172         JIT::compilePutByIdTransition(callFrame->scope()->vm(), codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress, direct);
173         return;
174     }
175     
176     stubInfo->initPutByIdReplace(callFrame->vm(), codeBlock->ownerExecutable(), structure);
177
178     JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress, direct);
179 }
180
181 NEVER_INLINE static void tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo)
182 {
183     ConcurrentJITLocker locker(codeBlock->m_lock);
184     
185     // FIXME: Write a test that proves we need to check for recursion here just
186     // like the interpreter does, then add a check for recursion.
187
188     // FIXME: Cache property access for immediates.
189     if (!baseValue.isCell()) {
190         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
191         return;
192     }
193     
194     VM* vm = &callFrame->vm();
195
196     if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
197         JIT::compilePatchGetArrayLength(callFrame->scope()->vm(), codeBlock, returnAddress);
198         return;
199     }
200     
201     if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
202         // The tradeoff of compiling an patched inline string length access routine does not seem
203         // to pay off, so we currently only do this for arrays.
204         ctiPatchCallByReturnAddress(codeBlock, returnAddress, vm->getCTIStub(stringLengthTrampolineGenerator).code());
205         return;
206     }
207
208     // Uncacheable: give up.
209     if (!slot.isCacheable()) {
210         stubInfo->accessType = access_get_by_id_generic;
211         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
212         return;
213     }
214
215     JSCell* baseCell = baseValue.asCell();
216     Structure* structure = baseCell->structure();
217
218     if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
219         stubInfo->accessType = access_get_by_id_generic;
220         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
221         return;
222     }
223
224     // Cache hit: Specialize instruction and ref Structures.
225
226     if (slot.slotBase() == baseValue) {
227         RELEASE_ASSERT(stubInfo->accessType == access_unset);
228         if (!slot.isCacheableValue() || !MacroAssembler::isCompactPtrAlignedAddressOffset(maxOffsetRelativeToPatchedStorage(slot.cachedOffset())))
229             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
230         else {
231             JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
232             stubInfo->initGetByIdSelf(callFrame->vm(), codeBlock->ownerExecutable(), structure);
233         }
234         return;
235     }
236
237     if (structure->isDictionary()) {
238         stubInfo->accessType = access_get_by_id_generic;
239         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
240         return;
241     }
242
243     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
244         JSObject* slotBaseObject = asObject(slot.slotBase());
245         size_t offset = slot.cachedOffset();
246
247         if (structure->typeInfo().hasImpureGetOwnPropertySlot()) {
248             stubInfo->accessType = access_get_by_id_generic;
249             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
250             return;
251         }
252         
253         // Since we're accessing a prototype in a loop, it's a good bet that it
254         // should not be treated as a dictionary.
255         if (slotBaseObject->structure()->isDictionary()) {
256             slotBaseObject->flattenDictionaryObject(callFrame->vm());
257             offset = slotBaseObject->structure()->get(callFrame->vm(), propertyName);
258         }
259         
260         stubInfo->initGetByIdProto(callFrame->vm(), codeBlock->ownerExecutable(), structure, slotBaseObject->structure(), slot.isCacheableValue());
261
262         ASSERT(!structure->isDictionary());
263         ASSERT(!slotBaseObject->structure()->isDictionary());
264         JIT::compileGetByIdProto(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), propertyName, slot, offset, returnAddress);
265         return;
266     }
267
268     PropertyOffset offset = slot.cachedOffset();
269     size_t count = normalizePrototypeChainForChainAccess(callFrame, baseValue, slot.slotBase(), propertyName, offset);
270     if (count == InvalidPrototypeChain) {
271         stubInfo->accessType = access_get_by_id_generic;
272         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
273         return;
274     }
275
276     StructureChain* prototypeChain = structure->prototypeChain(callFrame);
277     stubInfo->initGetByIdChain(callFrame->vm(), codeBlock->ownerExecutable(), structure, prototypeChain, count, slot.isCacheableValue());
278     JIT::compileGetByIdChain(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
279 }
280
281 #if !defined(NDEBUG)
282
283 extern "C" {
284
285 static void jscGeneratedNativeCode() 
286 {
287     // When executing a JIT stub function (which might do an allocation), we hack the return address
288     // to pretend to be executing this function, to keep stack logging tools from blowing out
289     // memory.
290 }
291
292 }
293
294 struct StackHack {
295     ALWAYS_INLINE StackHack(JITStackFrame& stackFrame) 
296         : stackFrame(stackFrame)
297         , savedReturnAddress(*stackFrame.returnAddressSlot())
298     {
299         if (!CodeProfiling::enabled())
300             *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
301     }
302
303     ALWAYS_INLINE ~StackHack() 
304     { 
305         *stackFrame.returnAddressSlot() = savedReturnAddress;
306     }
307
308     JITStackFrame& stackFrame;
309     ReturnAddressPtr savedReturnAddress;
310 };
311
312 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
313 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
314 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
315
316 #else
317
318 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS)
319 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
320 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
321
322 #endif
323
324 // The reason this is not inlined is to avoid having to do a PIC branch
325 // to get the address of the ctiVMThrowTrampoline function. It's also
326 // good to keep the code size down by leaving as much of the exception
327 // handling code out of line as possible.
328 static NEVER_INLINE void returnToThrowTrampoline(VM* vm, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
329 {
330     RELEASE_ASSERT(vm->exception());
331     vm->exceptionLocation = exceptionLocation;
332     returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline));
333 }
334
335 #define VM_THROW_EXCEPTION() \
336     do { \
337         VM_THROW_EXCEPTION_AT_END(); \
338         return 0; \
339     } while (0)
340 #define VM_THROW_EXCEPTION_AT_END() \
341     do {\
342         returnToThrowTrampoline(stackFrame.vm, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS);\
343     } while (0)
344
345 #define CHECK_FOR_EXCEPTION() \
346     do { \
347         if (UNLIKELY(stackFrame.vm->exception())) \
348             VM_THROW_EXCEPTION(); \
349     } while (0)
350 #define CHECK_FOR_EXCEPTION_AT_END() \
351     do { \
352         if (UNLIKELY(stackFrame.vm->exception())) \
353             VM_THROW_EXCEPTION_AT_END(); \
354     } while (0)
355 #define CHECK_FOR_EXCEPTION_VOID() \
356     do { \
357         if (UNLIKELY(stackFrame.vm->exception())) { \
358             VM_THROW_EXCEPTION_AT_END(); \
359             return; \
360         } \
361     } while (0)
362
363 class ErrorFunctor {
364 public:
365     virtual ~ErrorFunctor() { }
366     virtual JSValue operator()(ExecState*) = 0;
367 };
368
369 class ErrorWithExecFunctor : public ErrorFunctor {
370 public:
371     typedef JSObject* (*Factory)(ExecState* exec);
372     
373     ErrorWithExecFunctor(Factory factory)
374         : m_factory(factory)
375     {
376     }
377     JSValue operator()(ExecState* exec)
378     {
379         return m_factory(exec);
380     }
381
382 private:
383     Factory m_factory;
384 };
385
386 class ErrorWithExecAndCalleeFunctor : public ErrorFunctor {
387 public:
388     typedef JSObject* (*Factory)(ExecState* exec, JSValue callee);
389
390     ErrorWithExecAndCalleeFunctor(Factory factory, JSValue callee)
391         : m_factory(factory), m_callee(callee)
392     {
393     }
394     JSValue operator()(ExecState* exec)
395     {
396         return m_factory(exec, m_callee);
397     }
398 private:
399     Factory m_factory;
400     JSValue m_callee;
401 };
402
403 // Helper function for JIT stubs that may throw an exception in the middle of
404 // processing a function call. This function rolls back the stack to
405 // our caller, so exception processing can proceed from a valid state.
406 template<typename T> static T throwExceptionFromOpCall(JITStackFrame& jitStackFrame, CallFrame* newCallFrame, ReturnAddressPtr& returnAddressSlot, ErrorFunctor* createError = 0)
407 {
408     CallFrame* callFrame = newCallFrame->callerFrame()->removeHostCallFrameFlag();
409     jitStackFrame.callFrame = callFrame;
410     callFrame->vm().topCallFrame = callFrame;
411     if (createError)
412         callFrame->vm().throwException(callFrame, (*createError)(callFrame));
413     ASSERT(callFrame->vm().exception());
414     returnToThrowTrampoline(&callFrame->vm(), ReturnAddressPtr(newCallFrame->returnPC()), returnAddressSlot);
415     return T();
416 }
417
418 // If the CPU specific header does not provide an implementation, use the default one here.
419 #ifndef DEFINE_STUB_FUNCTION
420 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
421 #endif
422
423 DEFINE_STUB_FUNCTION(void, handle_watchdog_timer)
424 {
425     STUB_INIT_STACK_FRAME(stackFrame);
426     CallFrame* callFrame = stackFrame.callFrame;
427     VM* vm = stackFrame.vm;
428     if (UNLIKELY(vm->watchdog.didFire(callFrame))) {
429         vm->throwException(callFrame, createTerminatedExecutionException(vm));
430         VM_THROW_EXCEPTION_AT_END();
431         return;
432     }
433 }
434
435 DEFINE_STUB_FUNCTION(void*, stack_check)
436 {
437     STUB_INIT_STACK_FRAME(stackFrame);
438     CallFrame* callFrame = stackFrame.callFrame;
439
440     if (UNLIKELY(!stackFrame.stack->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters]))) {
441         ErrorWithExecFunctor functor = ErrorWithExecFunctor(createStackOverflowError);
442         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, &functor);
443     }
444
445     return callFrame;
446 }
447
448 DEFINE_STUB_FUNCTION(JSObject*, op_new_object)
449 {
450     STUB_INIT_STACK_FRAME(stackFrame);
451
452     return constructEmptyObject(stackFrame.callFrame, stackFrame.args[0].structure());
453 }
454
455 DEFINE_STUB_FUNCTION(void, op_put_by_id_generic)
456 {
457     STUB_INIT_STACK_FRAME(stackFrame);
458
459     PutPropertySlot slot(
460         stackFrame.callFrame->codeBlock()->isStrictMode(),
461         stackFrame.callFrame->codeBlock()->putByIdContext());
462     stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
463     CHECK_FOR_EXCEPTION_AT_END();
464 }
465
466 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
467 {
468     STUB_INIT_STACK_FRAME(stackFrame);
469     
470     PutPropertySlot slot(
471         stackFrame.callFrame->codeBlock()->isStrictMode(),
472         stackFrame.callFrame->codeBlock()->putByIdContext());
473     JSValue baseValue = stackFrame.args[0].jsValue();
474     ASSERT(baseValue.isObject());
475     asObject(baseValue)->putDirect(stackFrame.callFrame->vm(), stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
476     CHECK_FOR_EXCEPTION_AT_END();
477 }
478
479 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
480 {
481     STUB_INIT_STACK_FRAME(stackFrame);
482
483     CallFrame* callFrame = stackFrame.callFrame;
484     Identifier& ident = stackFrame.args[1].identifier();
485
486     JSValue baseValue = stackFrame.args[0].jsValue();
487     PropertySlot slot(baseValue);
488     JSValue result = baseValue.get(callFrame, ident, slot);
489
490     CHECK_FOR_EXCEPTION_AT_END();
491     return JSValue::encode(result);
492 }
493
494 DEFINE_STUB_FUNCTION(void, op_put_by_id)
495 {
496     STUB_INIT_STACK_FRAME(stackFrame);
497     CallFrame* callFrame = stackFrame.callFrame;
498     Identifier& ident = stackFrame.args[1].identifier();
499     
500     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
501     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
502     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
503
504     PutPropertySlot slot(
505         callFrame->codeBlock()->isStrictMode(),
506         callFrame->codeBlock()->putByIdContext());
507     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
508     
509     if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
510         stubInfo->setSeen();
511         tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false);
512     }
513     
514     CHECK_FOR_EXCEPTION_AT_END();
515 }
516
517 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
518 {
519     STUB_INIT_STACK_FRAME(stackFrame);
520     CallFrame* callFrame = stackFrame.callFrame;
521     Identifier& ident = stackFrame.args[1].identifier();
522     
523     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
524     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
525     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
526
527     PutPropertySlot slot(
528         callFrame->codeBlock()->isStrictMode(),
529         callFrame->codeBlock()->putByIdContext());
530     JSValue baseValue = stackFrame.args[0].jsValue();
531     ASSERT(baseValue.isObject());
532     
533     asObject(baseValue)->putDirect(callFrame->vm(), ident, stackFrame.args[2].jsValue(), slot);
534     
535     if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
536         stubInfo->setSeen();
537         tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true);
538     }
539     
540     CHECK_FOR_EXCEPTION_AT_END();
541 }
542
543 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
544 {
545     STUB_INIT_STACK_FRAME(stackFrame);
546
547     CallFrame* callFrame = stackFrame.callFrame;
548     Identifier& ident = stackFrame.args[1].identifier();
549     
550     PutPropertySlot slot(
551         callFrame->codeBlock()->isStrictMode(),
552         callFrame->codeBlock()->putByIdContext());
553     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
554
555     CHECK_FOR_EXCEPTION_AT_END();
556 }
557
558 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
559 {
560     STUB_INIT_STACK_FRAME(stackFrame);
561     
562     CallFrame* callFrame = stackFrame.callFrame;
563     Identifier& ident = stackFrame.args[1].identifier();
564     
565     PutPropertySlot slot(
566         callFrame->codeBlock()->isStrictMode(),
567         callFrame->codeBlock()->putByIdContext());
568     JSValue baseValue = stackFrame.args[0].jsValue();
569     ASSERT(baseValue.isObject());
570     asObject(baseValue)->putDirect(callFrame->vm(), ident, stackFrame.args[2].jsValue(), slot);
571     
572     CHECK_FOR_EXCEPTION_AT_END();
573 }
574
575 DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
576 {
577     STUB_INIT_STACK_FRAME(stackFrame);
578
579     JSValue baseValue = stackFrame.args[0].jsValue();
580     int32_t oldSize = stackFrame.args[3].int32();
581     Structure* newStructure = stackFrame.args[4].structure();
582     int32_t newSize = newStructure->outOfLineCapacity();
583     
584     ASSERT(oldSize >= 0);
585     ASSERT(newSize > oldSize);
586
587     ASSERT(baseValue.isObject());
588     JSObject* base = asObject(baseValue);
589     VM& vm = *stackFrame.vm;
590     Butterfly* butterfly = base->growOutOfLineStorage(vm, oldSize, newSize);
591     base->setStructureAndButterfly(vm, newStructure, butterfly);
592
593     return base;
594 }
595
596 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
597 {
598     STUB_INIT_STACK_FRAME(stackFrame);
599     CallFrame* callFrame = stackFrame.callFrame;
600     Identifier& ident = stackFrame.args[1].identifier();
601
602     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
603     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
604     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
605
606     JSValue baseValue = stackFrame.args[0].jsValue();
607     PropertySlot slot(baseValue);
608     JSValue result = baseValue.get(callFrame, ident, slot);
609     
610     if (accessType != static_cast<AccessType>(stubInfo->accessType))
611         return JSValue::encode(result);
612
613     if (!stubInfo->seenOnce())
614         stubInfo->setSeen();
615     else
616         tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo);
617
618     CHECK_FOR_EXCEPTION_AT_END();
619     return JSValue::encode(result);
620 }
621
622 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
623 {
624     STUB_INIT_STACK_FRAME(stackFrame);
625
626     CallFrame* callFrame = stackFrame.callFrame;
627     Identifier& ident = stackFrame.args[1].identifier();
628
629     CodeBlock* codeBlock = callFrame->codeBlock();
630     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
631     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
632
633     JSValue baseValue = stackFrame.args[0].jsValue();
634     PropertySlot slot(baseValue);
635     JSValue result = baseValue.get(callFrame, ident, slot);
636     
637     if (accessType != static_cast<AccessType>(stubInfo->accessType))
638         return JSValue::encode(result);
639
640     CHECK_FOR_EXCEPTION();
641
642     ConcurrentJITLocker locker(codeBlock->m_lock);
643     
644     if (baseValue.isCell()
645         && slot.isCacheable()
646         && !baseValue.asCell()->structure()->isUncacheableDictionary()
647         && slot.slotBase() == baseValue) {
648
649         PolymorphicAccessStructureList* polymorphicStructureList;
650         int listIndex = 1;
651
652         if (stubInfo->accessType == access_unset)
653             stubInfo->initGetByIdSelf(callFrame->vm(), codeBlock->ownerExecutable(), baseValue.asCell()->structure());
654
655         if (stubInfo->accessType == access_get_by_id_self) {
656             ASSERT(!stubInfo->stubRoutine);
657             polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->vm(), codeBlock->ownerExecutable(), 0, stubInfo->u.getByIdSelf.baseObjectStructure.get(), true);
658             stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
659         } else {
660             polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
661             listIndex = stubInfo->u.getByIdSelfList.listSize;
662         }
663         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
664             stubInfo->u.getByIdSelfList.listSize++;
665             JIT::compileGetByIdSelfList(callFrame->scope()->vm(), codeBlock, stubInfo, polymorphicStructureList, listIndex, baseValue.asCell()->structure(), ident, slot, slot.cachedOffset());
666
667             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
668                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
669         }
670     } else
671         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
672     return JSValue::encode(result);
673 }
674
675 static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(VM& vm, ScriptExecutable* owner, StructureStubInfo* stubInfo, int& listIndex)
676 {
677     PolymorphicAccessStructureList* prototypeStructureList = 0;
678     listIndex = 1;
679
680     switch (stubInfo->accessType) {
681     case access_get_by_id_proto:
682         prototypeStructureList = new PolymorphicAccessStructureList(vm, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get(), true);
683         stubInfo->stubRoutine.clear();
684         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
685         break;
686     case access_get_by_id_chain:
687         prototypeStructureList = new PolymorphicAccessStructureList(vm, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get(), true);
688         stubInfo->stubRoutine.clear();
689         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
690         break;
691     case access_get_by_id_proto_list:
692         prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
693         listIndex = stubInfo->u.getByIdProtoList.listSize;
694         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE)
695             stubInfo->u.getByIdProtoList.listSize++;
696         break;
697     default:
698         RELEASE_ASSERT_NOT_REACHED();
699     }
700     
701     ASSERT(listIndex <= POLYMORPHIC_LIST_CACHE_SIZE);
702     return prototypeStructureList;
703 }
704
705 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_getter_stub)
706 {
707     STUB_INIT_STACK_FRAME(stackFrame);
708     CallFrame* callFrame = stackFrame.callFrame;
709     JSValue result = callGetter(callFrame, stackFrame.args[1].jsObject(), stackFrame.args[0].jsObject());
710     if (callFrame->hadException())
711         returnToThrowTrampoline(&callFrame->vm(), stackFrame.args[2].returnAddress(), STUB_RETURN_ADDRESS);
712
713     return JSValue::encode(result);
714 }
715
716 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_custom_stub)
717 {
718     STUB_INIT_STACK_FRAME(stackFrame);
719     CallFrame* callFrame = stackFrame.callFrame;
720     JSObject* slotBase = stackFrame.args[0].jsObject();
721     PropertySlot::GetValueFunc getter = reinterpret_cast<PropertySlot::GetValueFunc>(stackFrame.args[1].asPointer);
722     const Identifier& ident = stackFrame.args[2].identifier();
723     JSValue result = getter(callFrame, slotBase, ident);
724     if (callFrame->hadException())
725         returnToThrowTrampoline(&callFrame->vm(), stackFrame.args[3].returnAddress(), STUB_RETURN_ADDRESS);
726     
727     return JSValue::encode(result);
728 }
729
730 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
731 {
732     STUB_INIT_STACK_FRAME(stackFrame);
733
734     CallFrame* callFrame = stackFrame.callFrame;
735     const Identifier& propertyName = stackFrame.args[1].identifier();
736
737     CodeBlock* codeBlock = callFrame->codeBlock();
738     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
739     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
740
741     JSValue baseValue = stackFrame.args[0].jsValue();
742     PropertySlot slot(baseValue);
743     JSValue result = baseValue.get(callFrame, propertyName, slot);
744
745     CHECK_FOR_EXCEPTION();
746
747     if (accessType != static_cast<AccessType>(stubInfo->accessType)
748         || !baseValue.isCell()
749         || !slot.isCacheable()
750         || baseValue.asCell()->structure()->isDictionary()
751         || baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()) {
752         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
753         return JSValue::encode(result);
754     }
755
756     ConcurrentJITLocker locker(codeBlock->m_lock);
757     
758     Structure* structure = baseValue.asCell()->structure();
759
760     JSObject* slotBaseObject = asObject(slot.slotBase());
761     
762     PropertyOffset offset = slot.cachedOffset();
763
764     if (slot.slotBase() == baseValue)
765         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
766     else if (slot.slotBase() == baseValue.asCell()->structure()->prototypeForLookup(callFrame)) {
767         ASSERT(!baseValue.asCell()->structure()->isDictionary());
768         
769         if (baseValue.asCell()->structure()->typeInfo().hasImpureGetOwnPropertySlot()) {
770             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
771             return JSValue::encode(result);
772         }
773         
774         // Since we're accessing a prototype in a loop, it's a good bet that it
775         // should not be treated as a dictionary.
776         if (slotBaseObject->structure()->isDictionary()) {
777             slotBaseObject->flattenDictionaryObject(callFrame->vm());
778             offset = slotBaseObject->structure()->get(callFrame->vm(), propertyName);
779         }
780
781         int listIndex;
782         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->vm(), codeBlock->ownerExecutable(), stubInfo, listIndex);
783         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
784             JIT::compileGetByIdProtoList(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset);
785
786             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
787                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
788         }
789     } else {
790         size_t count = normalizePrototypeChainForChainAccess(callFrame, baseValue, slot.slotBase(), propertyName, offset);
791         if (count == InvalidPrototypeChain) {
792             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
793             return JSValue::encode(result);
794         }
795         
796         ASSERT(!baseValue.asCell()->structure()->isDictionary());
797         int listIndex;
798         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->vm(), codeBlock->ownerExecutable(), stubInfo, listIndex);
799         
800         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
801             StructureChain* protoChain = structure->prototypeChain(callFrame);
802             JIT::compileGetByIdChainList(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, propertyName, slot, offset);
803
804             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
805                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
806         }
807     }
808
809     return JSValue::encode(result);
810 }
811
812 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list_full)
813 {
814     STUB_INIT_STACK_FRAME(stackFrame);
815
816     JSValue baseValue = stackFrame.args[0].jsValue();
817     PropertySlot slot(baseValue);
818     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
819
820     CHECK_FOR_EXCEPTION_AT_END();
821     return JSValue::encode(result);
822 }
823
824 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_fail)
825 {
826     STUB_INIT_STACK_FRAME(stackFrame);
827
828     JSValue baseValue = stackFrame.args[0].jsValue();
829     PropertySlot slot(baseValue);
830     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
831
832     CHECK_FOR_EXCEPTION_AT_END();
833     return JSValue::encode(result);
834 }
835
836 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_array_fail)
837 {
838     STUB_INIT_STACK_FRAME(stackFrame);
839
840     JSValue baseValue = stackFrame.args[0].jsValue();
841     PropertySlot slot(baseValue);
842     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
843
844     CHECK_FOR_EXCEPTION_AT_END();
845     return JSValue::encode(result);
846 }
847
848 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail)
849 {
850     STUB_INIT_STACK_FRAME(stackFrame);
851
852     JSValue baseValue = stackFrame.args[0].jsValue();
853     PropertySlot slot(baseValue);
854     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
855
856     CHECK_FOR_EXCEPTION_AT_END();
857     return JSValue::encode(result);
858 }
859
860 DEFINE_STUB_FUNCTION(EncodedJSValue, op_check_has_instance)
861 {
862     STUB_INIT_STACK_FRAME(stackFrame);
863
864     CallFrame* callFrame = stackFrame.callFrame;
865     JSValue value = stackFrame.args[0].jsValue();
866     JSValue baseVal = stackFrame.args[1].jsValue();
867
868     if (baseVal.isObject()) {
869         JSObject* baseObject = asObject(baseVal);
870         ASSERT(!baseObject->structure()->typeInfo().implementsDefaultHasInstance());
871         if (baseObject->structure()->typeInfo().implementsHasInstance()) {
872             bool result = baseObject->methodTable()->customHasInstance(baseObject, callFrame, value);
873             CHECK_FOR_EXCEPTION_AT_END();
874             return JSValue::encode(jsBoolean(result));
875         }
876     }
877
878     stackFrame.vm->throwException(callFrame, createInvalidParameterError(callFrame, "instanceof", baseVal));
879     VM_THROW_EXCEPTION_AT_END();
880     return JSValue::encode(JSValue());
881 }
882
883 #if ENABLE(DFG_JIT)
884 DEFINE_STUB_FUNCTION(void, optimize)
885 {
886     STUB_INIT_STACK_FRAME(stackFrame);
887     
888     // Defer GC so that it doesn't run between when we enter into this slow path and
889     // when we figure out the state of our code block. This prevents a number of
890     // awkward reentrancy scenarios, including:
891     //
892     // - The optimized version of our code block being jettisoned by GC right after
893     //   we concluded that we wanted to use it.
894     //
895     // - An optimized version of our code block being installed just as we decided
896     //   that it wasn't ready yet.
897     //
898     // This still leaves the following: anytime we return from cti_optimize, we may
899     // GC, and the GC may either jettison the optimized version of our code block,
900     // or it may install the optimized version of our code block even though we
901     // concluded that it wasn't ready yet.
902     //
903     // Note that jettisoning won't happen if we already initiated OSR, because in
904     // that case we would have already planted the optimized code block into the JS
905     // stack.
906     DeferGC deferGC(stackFrame.vm->heap);
907     
908     CallFrame* callFrame = stackFrame.callFrame;
909     CodeBlock* codeBlock = callFrame->codeBlock();
910     VM& vm = callFrame->vm();
911     unsigned bytecodeIndex = stackFrame.args[0].int32();
912
913     if (bytecodeIndex) {
914         // If we're attempting to OSR from a loop, assume that this should be
915         // separately optimized.
916         codeBlock->m_shouldAlwaysBeInlined = false;
917     }
918     
919     if (Options::verboseOSR()) {
920         dataLog(
921             *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex,
922             ", executeCounter = ", codeBlock->jitExecuteCounter(),
923             ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(),
924             ", exitCounter = ");
925         if (codeBlock->hasOptimizedReplacement())
926             dataLog(codeBlock->replacement()->osrExitCounter());
927         else
928             dataLog("N/A");
929         dataLog("\n");
930     }
931
932     if (!codeBlock->checkIfOptimizationThresholdReached()) {
933         codeBlock->updateAllPredictions();
934         if (Options::verboseOSR())
935             dataLog("Choosing not to optimize ", *codeBlock, " yet, because the threshold hasn't been reached.\n");
936         return;
937     }
938     
939     if (codeBlock->m_shouldAlwaysBeInlined) {
940         codeBlock->updateAllPredictions();
941         codeBlock->optimizeAfterWarmUp();
942         if (Options::verboseOSR())
943             dataLog("Choosing not to optimize ", *codeBlock, " yet, because m_shouldAlwaysBeInlined == true.\n");
944         return;
945     }
946     
947     // We cannot be in the process of asynchronous compilation and also have an optimized
948     // replacement.
949     ASSERT(
950         !vm.worklist
951         || !(vm.worklist->compilationState(codeBlock) != DFG::Worklist::NotKnown
952              && codeBlock->hasOptimizedReplacement()));
953     
954     DFG::Worklist::State worklistState;
955     if (vm.worklist) {
956         // The call to DFG::Worklist::completeAllReadyPlansForVM() will complete all ready
957         // (i.e. compiled) code blocks. But if it completes ours, we also need to know
958         // what the result was so that we don't plow ahead and attempt OSR or immediate
959         // reoptimization. This will have already also set the appropriate JIT execution
960         // count threshold depending on what happened, so if the compilation was anything
961         // but successful we just want to return early. See the case for worklistState ==
962         // DFG::Worklist::Compiled, below.
963         
964         // Note that we could have alternatively just called Worklist::compilationState()
965         // here, and if it returned Compiled, we could have then called
966         // completeAndScheduleOSR() below. But that would have meant that it could take
967         // longer for code blocks to be completed: they would only complete when *their*
968         // execution count trigger fired; but that could take a while since the firing is
969         // racy. It could also mean that code blocks that never run again after being
970         // compiled would sit on the worklist until next GC. That's fine, but it's
971         // probably a waste of memory. Our goal here is to complete code blocks as soon as
972         // possible in order to minimize the chances of us executing baseline code after
973         // optimized code is already available.
974         
975         worklistState =
976             vm.worklist->completeAllReadyPlansForVM(vm, codeBlock);
977     } else
978         worklistState = DFG::Worklist::NotKnown;
979     
980     if (worklistState == DFG::Worklist::Compiling) {
981         // We cannot be in the process of asynchronous compilation and also have an optimized
982         // replacement.
983         RELEASE_ASSERT(!codeBlock->hasOptimizedReplacement());
984         codeBlock->setOptimizationThresholdBasedOnCompilationResult(CompilationDeferred);
985         return;
986     }
987     
988     if (worklistState == DFG::Worklist::Compiled) {
989         // If we don't have an optimized replacement but we did just get compiled, then
990         // the compilation failed or was invalidated, in which case the execution count
991         // thresholds have already been set appropriately by
992         // CodeBlock::setOptimizationThresholdBasedOnCompilationResult() and we have
993         // nothing left to do.
994         if (!codeBlock->hasOptimizedReplacement()) {
995             codeBlock->updateAllPredictions();
996             if (Options::verboseOSR())
997                 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
998             return;
999         }
1000     } else if (codeBlock->hasOptimizedReplacement()) {
1001         if (Options::verboseOSR())
1002             dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
1003         // If we have an optimized replacement, then it must be the case that we entered
1004         // cti_optimize from a loop. That's because if there's an optimized replacement,
1005         // then all calls to this function will be relinked to the replacement and so
1006         // the prologue OSR will never fire.
1007         
1008         // This is an interesting threshold check. Consider that a function OSR exits
1009         // in the middle of a loop, while having a relatively low exit count. The exit
1010         // will reset the execution counter to some target threshold, meaning that this
1011         // code won't be reached until that loop heats up for >=1000 executions. But then
1012         // we do a second check here, to see if we should either reoptimize, or just
1013         // attempt OSR entry. Hence it might even be correct for
1014         // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
1015         // additional checking anyway, to reduce the amount of recompilation thrashing.
1016         if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
1017             if (Options::verboseOSR()) {
1018                 dataLog(
1019                     "Triggering reoptimization of ", *codeBlock,
1020                     "(", *codeBlock->replacement(), ") (in loop).\n");
1021             }
1022             codeBlock->reoptimize();
1023             return;
1024         }
1025     } else {
1026         if (!codeBlock->shouldOptimizeNow()) {
1027             if (Options::verboseOSR()) {
1028                 dataLog(
1029                     "Delaying optimization for ", *codeBlock,
1030                     " because of insufficient profiling.\n");
1031             }
1032             return;
1033         }
1034         
1035         if (Options::verboseOSR())
1036             dataLog("Triggering optimized compilation of ", *codeBlock, "\n");
1037         
1038         RefPtr<DeferredCompilationCallback> callback =
1039             JITToDFGDeferredCompilationCallback::create();
1040         RefPtr<CodeBlock> newCodeBlock = codeBlock->newReplacement();
1041         
1042         if (!vm.worklist)
1043             vm.worklist = DFG::globalWorklist();
1044         
1045         CompilationResult result = DFG::compile(
1046             callFrame, newCodeBlock.get(), bytecodeIndex, callback, vm.worklist.get());
1047         
1048         if (result != CompilationSuccessful)
1049             return;
1050     }
1051     
1052     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1053     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1054     
1055     if (optimizedCodeBlock->jitType() == JITCode::FTLJIT) {
1056         // FTL JIT doesn't support OSR entry yet.
1057         // https://bugs.webkit.org/show_bug.cgi?id=113625
1058         
1059         // Don't attempt OSR entry again.
1060         codeBlock->dontOptimizeAnytimeSoon();
1061         return;
1062     }
1063     
1064     if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) {
1065         if (Options::verboseOSR()) {
1066             dataLog(
1067                 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ", address ",
1068                 RawPointer((STUB_RETURN_ADDRESS).value()), " -> ", RawPointer(address), ".\n");
1069         }
1070
1071         codeBlock->optimizeSoon();
1072         STUB_SET_RETURN_ADDRESS(address);
1073         return;
1074     }
1075
1076     if (Options::verboseOSR()) {
1077         dataLog(
1078             "Optimizing ", *codeBlock, " -> ", *codeBlock->replacement(),
1079             " succeeded, OSR failed, after a delay of ",
1080             codeBlock->optimizationDelayCounter(), ".\n");
1081     }
1082
1083     // Count the OSR failure as a speculation failure. If this happens a lot, then
1084     // reoptimize.
1085     optimizedCodeBlock->countOSRExit();
1086     
1087     // We are a lot more conservative about triggering reoptimization after OSR failure than
1088     // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
1089     // already, then we really would like to reoptimize immediately. But this case covers
1090     // something else: there weren't many (or any) speculation failures before, but we just
1091     // failed to enter the speculative code because some variable had the wrong value or
1092     // because the OSR code decided for any spurious reason that it did not want to OSR
1093     // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
1094     // reoptimization trigger.
1095     if (optimizedCodeBlock->shouldReoptimizeNow()) {
1096         if (Options::verboseOSR()) {
1097             dataLog(
1098                 "Triggering reoptimization of ", *codeBlock, " -> ",
1099                 *codeBlock->replacement(), " (after OSR fail).\n");
1100         }
1101         codeBlock->reoptimize();
1102         return;
1103     }
1104
1105     // OSR failed this time, but it might succeed next time! Let the code run a bit
1106     // longer and then try again.
1107     codeBlock->optimizeAfterWarmUp();
1108 }
1109 #endif // ENABLE(DFG_JIT)
1110
1111 DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
1112 {
1113     STUB_INIT_STACK_FRAME(stackFrame);
1114
1115     CallFrame* callFrame = stackFrame.callFrame;
1116     JSValue value = stackFrame.args[0].jsValue();
1117     JSValue proto = stackFrame.args[1].jsValue();
1118     
1119     ASSERT(!value.isObject() || !proto.isObject());
1120
1121     bool result = JSObject::defaultHasInstance(callFrame, value, proto);
1122     CHECK_FOR_EXCEPTION_AT_END();
1123     return JSValue::encode(jsBoolean(result));
1124 }
1125
1126 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
1127 {
1128     STUB_INIT_STACK_FRAME(stackFrame);
1129
1130     CallFrame* callFrame = stackFrame.callFrame;
1131     
1132     JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
1133
1134     bool couldDelete = baseObj->methodTable()->deleteProperty(baseObj, callFrame, stackFrame.args[1].identifier());
1135     JSValue result = jsBoolean(couldDelete);
1136     if (!couldDelete && callFrame->codeBlock()->isStrictMode())
1137         stackFrame.vm->throwException(stackFrame.callFrame, createTypeError(stackFrame.callFrame, "Unable to delete property."));
1138
1139     CHECK_FOR_EXCEPTION_AT_END();
1140     return JSValue::encode(result);
1141 }
1142
1143 DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
1144 {
1145     STUB_INIT_STACK_FRAME(stackFrame);
1146     
1147     ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
1148     return JSFunction::create(stackFrame.callFrame, stackFrame.args[0].function(), stackFrame.callFrame->scope());
1149 }
1150
1151 inline void* jitCompileFor(CallFrame* callFrame, CodeSpecializationKind kind)
1152 {
1153     // This function is called by cti_op_call_jitCompile() and
1154     // cti_op_construct_jitCompile() JIT glue trampolines to compile the
1155     // callee function that we want to call. Both cti glue trampolines are
1156     // called by JIT'ed code which has pushed a frame and initialized most of
1157     // the frame content except for the codeBlock.
1158     //
1159     // Normally, the prologue of the callee is supposed to set the frame's cb
1160     // pointer to the cb of the callee. But in this case, the callee code does
1161     // not exist yet until it is compiled below. The compilation process will
1162     // allocate memory which may trigger a GC. The GC, in turn, will scan the
1163     // JSStack, and will expect the frame's cb to either be valid or 0. If
1164     // we don't initialize it, the GC will be accessing invalid memory and may
1165     // crash.
1166     //
1167     // Hence, we should nullify it here before proceeding with the compilation.
1168     callFrame->setCodeBlock(0);
1169
1170     JSFunction* function = jsCast<JSFunction*>(callFrame->callee());
1171     ASSERT(!function->isHostFunction());
1172     FunctionExecutable* executable = function->jsExecutable();
1173     JSScope* callDataScopeChain = function->scope();
1174     JSObject* error = executable->prepareForExecution(callFrame, callDataScopeChain, kind);
1175     if (!error)
1176         return function;
1177     callFrame->vm().throwException(callFrame, error);
1178     return 0;
1179 }
1180
1181 DEFINE_STUB_FUNCTION(void*, op_call_jitCompile)
1182 {
1183     STUB_INIT_STACK_FRAME(stackFrame);
1184
1185 #if !ASSERT_DISABLED
1186     CallData callData;
1187     ASSERT(stackFrame.callFrame->callee()->methodTable()->getCallData(stackFrame.callFrame->callee(), callData) == CallTypeJS);
1188 #endif
1189     
1190     CallFrame* callFrame = stackFrame.callFrame;
1191     void* result = jitCompileFor(callFrame, CodeForCall);
1192     if (!result)
1193         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1194
1195     return result;
1196 }
1197
1198 DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
1199 {
1200     STUB_INIT_STACK_FRAME(stackFrame);
1201
1202 #if !ASSERT_DISABLED
1203     ConstructData constructData;
1204     ASSERT(jsCast<JSFunction*>(stackFrame.callFrame->callee())->methodTable()->getConstructData(stackFrame.callFrame->callee(), constructData) == ConstructTypeJS);
1205 #endif
1206
1207     CallFrame* callFrame = stackFrame.callFrame;    
1208     void* result = jitCompileFor(callFrame, CodeForConstruct);
1209     if (!result)
1210         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1211
1212     return result;
1213 }
1214
1215 DEFINE_STUB_FUNCTION(int, op_call_arityCheck)
1216 {
1217     STUB_INIT_STACK_FRAME(stackFrame);
1218
1219     CallFrame* callFrame = stackFrame.callFrame;
1220
1221     int missingArgCount = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.stack, CodeForCall);
1222     if (missingArgCount < 0) {
1223         ErrorWithExecFunctor functor = ErrorWithExecFunctor(createStackOverflowError);
1224         return throwExceptionFromOpCall<int>(stackFrame, callFrame, STUB_RETURN_ADDRESS, &functor);
1225     }
1226     return missingArgCount;
1227 }
1228
1229 DEFINE_STUB_FUNCTION(int, op_construct_arityCheck)
1230 {
1231     STUB_INIT_STACK_FRAME(stackFrame);
1232
1233     CallFrame* callFrame = stackFrame.callFrame;
1234
1235     int missingArgCount = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.stack, CodeForConstruct);
1236     if (missingArgCount < 0) {
1237         ErrorWithExecFunctor functor = ErrorWithExecFunctor(createStackOverflowError);
1238         return throwExceptionFromOpCall<int>(stackFrame, callFrame, STUB_RETURN_ADDRESS, &functor);
1239     }
1240     return missingArgCount;
1241 }
1242
1243 inline void* lazyLinkFor(CallFrame* callFrame, CodeSpecializationKind kind)
1244 {
1245     JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
1246     ExecutableBase* executable = callee->executable();
1247
1248     MacroAssemblerCodePtr codePtr;
1249     CodeBlock* codeBlock = 0;
1250     CallLinkInfo* callLinkInfo = &callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
1251
1252     // This function is called by cti_vm_lazyLinkCall() and
1253     // cti_lazyLinkConstruct JIT glue trampolines to link the callee function
1254     // that we want to call. Both cti glue trampolines are called by JIT'ed
1255     // code which has pushed a frame and initialized most of the frame content
1256     // except for the codeBlock.
1257     //
1258     // Normally, the prologue of the callee is supposed to set the frame's cb
1259     // field to the cb of the callee. But in this case, the callee may not
1260     // exist yet, and if not, it will be generated in the compilation below.
1261     // The compilation will allocate memory which may trigger a GC. The GC, in
1262     // turn, will scan the JSStack, and will expect the frame's cb to be valid
1263     // or 0. If we don't initialize it, the GC will be accessing invalid
1264     // memory and may crash.
1265     //
1266     // Hence, we should nullify it here before proceeding with the compilation.
1267     callFrame->setCodeBlock(0);
1268
1269     if (executable->isHostFunction())
1270         codePtr = executable->generatedJITCodeFor(kind)->addressForCall();
1271     else {
1272         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
1273         if (JSObject* error = functionExecutable->prepareForExecution(callFrame, callee->scope(), kind)) {
1274             callFrame->vm().throwException(callFrame, error);
1275             return 0;
1276         }
1277         codeBlock = &functionExecutable->generatedBytecodeFor(kind);
1278         if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters())
1279             || callLinkInfo->callType == CallLinkInfo::CallVarargs)
1280             codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
1281         else
1282             codePtr = functionExecutable->generatedJITCodeFor(kind)->addressForCall();
1283     }
1284     
1285     ConcurrentJITLocker locker(callFrame->callerFrame()->codeBlock()->m_lock);
1286     if (!callLinkInfo->seenOnce())
1287         callLinkInfo->setSeen();
1288     else
1289         JIT::linkFor(callFrame->callerFrame(), callee, callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, &callFrame->vm(), kind);
1290
1291     return codePtr.executableAddress();
1292 }
1293
1294 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
1295 {
1296     STUB_INIT_STACK_FRAME(stackFrame);
1297
1298     CallFrame* callFrame = stackFrame.callFrame;
1299     void* result = lazyLinkFor(callFrame, CodeForCall);
1300     if (!result)
1301         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1302
1303     return result;
1304 }
1305
1306 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkClosureCall)
1307 {
1308     STUB_INIT_STACK_FRAME(stackFrame);
1309
1310     CallFrame* callFrame = stackFrame.callFrame;
1311     
1312     CodeBlock* callerCodeBlock = callFrame->callerFrame()->codeBlock();
1313     VM* vm = callerCodeBlock->vm();
1314     CallLinkInfo* callLinkInfo = &callerCodeBlock->getCallLinkInfo(callFrame->returnPC());
1315     JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
1316     ExecutableBase* executable = callee->executable();
1317     Structure* structure = callee->structure();
1318     
1319     ASSERT(callLinkInfo->callType == CallLinkInfo::Call);
1320     ASSERT(callLinkInfo->isLinked());
1321     ASSERT(callLinkInfo->callee);
1322     ASSERT(callee != callLinkInfo->callee.get());
1323     
1324     bool shouldLink = false;
1325     CodeBlock* calleeCodeBlock = 0;
1326     MacroAssemblerCodePtr codePtr;
1327     
1328     if (executable == callLinkInfo->callee.get()->executable()
1329         && structure == callLinkInfo->callee.get()->structure()) {
1330         
1331         shouldLink = true;
1332         
1333         ASSERT(executable->hasJITCodeForCall());
1334         codePtr = executable->generatedJITCodeForCall()->addressForCall();
1335         if (!callee->executable()->isHostFunction()) {
1336             calleeCodeBlock = &jsCast<FunctionExecutable*>(executable)->generatedBytecodeForCall();
1337             if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(calleeCodeBlock->numParameters())) {
1338                 shouldLink = false;
1339                 codePtr = executable->generatedJITCodeWithArityCheckFor(CodeForCall);
1340             }
1341         }
1342     } else if (callee->isHostFunction())
1343         codePtr = executable->generatedJITCodeForCall()->addressForCall();
1344     else {
1345         // Need to clear the code block before compilation, because compilation can GC.
1346         callFrame->setCodeBlock(0);
1347         
1348         FunctionExecutable* functionExecutable = jsCast<FunctionExecutable*>(executable);
1349         JSScope* scopeChain = callee->scope();
1350         JSObject* error = functionExecutable->prepareForExecution(callFrame, scopeChain, CodeForCall);
1351         if (error) {
1352             callFrame->vm().throwException(callFrame, error);
1353             return 0;
1354         }
1355         
1356         codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(CodeForCall);
1357     }
1358     
1359     if (shouldLink) {
1360         ASSERT(codePtr);
1361         ConcurrentJITLocker locker(callerCodeBlock->m_lock);
1362         JIT::compileClosureCall(vm, callLinkInfo, callerCodeBlock, calleeCodeBlock, structure, executable, codePtr);
1363         callLinkInfo->hasSeenClosure = true;
1364     } else
1365         JIT::linkSlowCall(callerCodeBlock, callLinkInfo);
1366
1367     return codePtr.executableAddress();
1368 }
1369
1370 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
1371 {
1372     STUB_INIT_STACK_FRAME(stackFrame);
1373
1374     CallFrame* callFrame = stackFrame.callFrame;
1375     void* result = lazyLinkFor(callFrame, CodeForConstruct);
1376     if (!result)
1377         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1378
1379     return result;
1380 }
1381
1382 DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
1383 {
1384     STUB_INIT_STACK_FRAME(stackFrame);
1385
1386     JSActivation* activation = JSActivation::create(stackFrame.callFrame->vm(), stackFrame.callFrame, stackFrame.callFrame->codeBlock());
1387     stackFrame.callFrame->setScope(activation);
1388     return activation;
1389 }
1390
1391 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
1392 {
1393     STUB_INIT_STACK_FRAME(stackFrame);
1394
1395     CallFrame* callFrame = stackFrame.callFrame;
1396     
1397     JSValue callee = callFrame->calleeAsValue();
1398
1399     CallData callData;
1400     CallType callType = getCallData(callee, callData);
1401
1402     ASSERT(callType != CallTypeJS);
1403     if (callType != CallTypeHost) {
1404         ASSERT(callType == CallTypeNone);
1405         ErrorWithExecAndCalleeFunctor functor = ErrorWithExecAndCalleeFunctor(createNotAFunctionError, callee);
1406         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, &functor);
1407     }
1408
1409     EncodedJSValue returnValue;
1410     {
1411         SamplingTool::CallRecord callRecord(CTI_SAMPLER, true);
1412         returnValue = callData.native.function(callFrame);
1413     }
1414
1415     if (stackFrame.vm->exception())
1416         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1417
1418     return returnValue;
1419 }
1420
1421 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments)
1422 {
1423     STUB_INIT_STACK_FRAME(stackFrame);
1424
1425     Arguments* arguments = Arguments::create(*stackFrame.vm, stackFrame.callFrame);
1426     return JSValue::encode(JSValue(arguments));
1427 }
1428
1429 DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
1430 {
1431     STUB_INIT_STACK_FRAME(stackFrame);
1432
1433     ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
1434     jsCast<JSActivation*>(stackFrame.args[0].jsValue())->tearOff(*stackFrame.vm);
1435 }
1436
1437 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
1438 {
1439     STUB_INIT_STACK_FRAME(stackFrame);
1440
1441     CallFrame* callFrame = stackFrame.callFrame;
1442     ASSERT(callFrame->codeBlock()->usesArguments());
1443     Arguments* arguments = jsCast<Arguments*>(stackFrame.args[0].jsValue());
1444     if (JSValue activationValue = stackFrame.args[1].jsValue()) {
1445         arguments->didTearOffActivation(callFrame, jsCast<JSActivation*>(activationValue));
1446         return;
1447     }
1448     arguments->tearOff(callFrame);
1449 }
1450
1451 DEFINE_STUB_FUNCTION(void, op_profile_will_call)
1452 {
1453     STUB_INIT_STACK_FRAME(stackFrame);
1454
1455     if (LegacyProfiler* profiler = stackFrame.vm->enabledProfiler())
1456         profiler->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
1457 }
1458
1459 DEFINE_STUB_FUNCTION(void, op_profile_did_call)
1460 {
1461     STUB_INIT_STACK_FRAME(stackFrame);
1462
1463     if (LegacyProfiler* profiler = stackFrame.vm->enabledProfiler())
1464         profiler->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
1465 }
1466
1467 DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
1468 {
1469     STUB_INIT_STACK_FRAME(stackFrame);
1470
1471     return constructArray(stackFrame.callFrame, stackFrame.args[2].arrayAllocationProfile(), reinterpret_cast<JSValue*>(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()]), stackFrame.args[1].int32());
1472 }
1473
1474 DEFINE_STUB_FUNCTION(JSObject*, op_new_array_with_size)
1475 {
1476     STUB_INIT_STACK_FRAME(stackFrame);
1477     
1478     return constructArrayWithSizeQuirk(stackFrame.callFrame, stackFrame.args[1].arrayAllocationProfile(), stackFrame.callFrame->lexicalGlobalObject(), stackFrame.args[0].jsValue());
1479 }
1480
1481 DEFINE_STUB_FUNCTION(JSObject*, op_new_array_buffer)
1482 {
1483     STUB_INIT_STACK_FRAME(stackFrame);
1484     
1485     return constructArray(stackFrame.callFrame, stackFrame.args[2].arrayAllocationProfile(), stackFrame.callFrame->codeBlock()->constantBuffer(stackFrame.args[0].int32()), stackFrame.args[1].int32());
1486 }
1487
1488 DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
1489 {
1490     STUB_INIT_STACK_FRAME(stackFrame);
1491
1492     CallFrame* callFrame = stackFrame.callFrame;
1493     JSValue callee = callFrame->calleeAsValue();
1494
1495     ConstructData constructData;
1496     ConstructType constructType = getConstructData(callee, constructData);
1497
1498     ASSERT(constructType != ConstructTypeJS);
1499     if (constructType != ConstructTypeHost) {
1500         ASSERT(constructType == ConstructTypeNone);
1501         ErrorWithExecAndCalleeFunctor functor = ErrorWithExecAndCalleeFunctor(createNotAConstructorError, callee);
1502         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, &functor);
1503     }
1504
1505     EncodedJSValue returnValue;
1506     {
1507         SamplingTool::CallRecord callRecord(CTI_SAMPLER, true);
1508         returnValue = constructData.native.function(callFrame);
1509     }
1510
1511     if (stackFrame.vm->exception())
1512         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1513
1514     return returnValue;
1515 }
1516
1517 static JSValue getByVal(
1518     CallFrame* callFrame, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress)
1519 {
1520     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1521         if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame)))
1522             return result;
1523     }
1524
1525     if (subscript.isUInt32()) {
1526         uint32_t i = subscript.asUInt32();
1527         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
1528             ctiPatchCallByReturnAddress(callFrame->codeBlock(), returnAddress, FunctionPtr(cti_op_get_by_val_string));
1529             return asString(baseValue)->getIndex(callFrame, i);
1530         }
1531         return baseValue.get(callFrame, i);
1532     }
1533
1534     if (isName(subscript))
1535         return baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName());
1536
1537     Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1538     return baseValue.get(callFrame, property);
1539 }
1540
1541 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
1542 {
1543     STUB_INIT_STACK_FRAME(stackFrame);
1544
1545     CallFrame* callFrame = stackFrame.callFrame;
1546
1547     JSValue baseValue = stackFrame.args[0].jsValue();
1548     JSValue subscript = stackFrame.args[1].jsValue();
1549     
1550     if (baseValue.isObject() && subscript.isInt32()) {
1551         // See if it's worth optimizing this at all.
1552         JSObject* object = asObject(baseValue);
1553         bool didOptimize = false;
1554
1555         unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
1556         ASSERT(bytecodeOffset);
1557         ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
1558         ASSERT(!byValInfo.stubRoutine);
1559         
1560         if (hasOptimizableIndexing(object->structure())) {
1561             // Attempt to optimize.
1562             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure());
1563             if (arrayMode != byValInfo.arrayMode) {
1564                 JIT::compileGetByVal(&callFrame->vm(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode);
1565                 didOptimize = true;
1566             }
1567         }
1568         
1569         if (!didOptimize) {
1570             // If we take slow path more than 10 times without patching then make sure we
1571             // never make that mistake again. Or, if we failed to patch and we have some object
1572             // that intercepts indexed get, then don't even wait until 10 times. For cases
1573             // where we see non-index-intercepting objects, this gives 10 iterations worth of
1574             // opportunity for us to observe that the get_by_val may be polymorphic.
1575             if (++byValInfo.slowPathCount >= 10
1576                 || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1577                 // Don't ever try to optimize.
1578                 RepatchBuffer repatchBuffer(callFrame->codeBlock());
1579                 repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_generic));
1580             }
1581         }
1582     }
1583     
1584     JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS);
1585     CHECK_FOR_EXCEPTION();
1586     return JSValue::encode(result);
1587 }
1588     
1589 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_generic)
1590 {
1591     STUB_INIT_STACK_FRAME(stackFrame);
1592
1593     CallFrame* callFrame = stackFrame.callFrame;
1594
1595     JSValue baseValue = stackFrame.args[0].jsValue();
1596     JSValue subscript = stackFrame.args[1].jsValue();
1597     
1598     JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS);
1599     CHECK_FOR_EXCEPTION();
1600     return JSValue::encode(result);
1601 }
1602     
1603 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
1604 {
1605     STUB_INIT_STACK_FRAME(stackFrame);
1606     
1607     CallFrame* callFrame = stackFrame.callFrame;
1608     
1609     JSValue baseValue = stackFrame.args[0].jsValue();
1610     JSValue subscript = stackFrame.args[1].jsValue();
1611     
1612     JSValue result;
1613     
1614     if (LIKELY(subscript.isUInt32())) {
1615         uint32_t i = subscript.asUInt32();
1616         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1617             result = asString(baseValue)->getIndex(callFrame, i);
1618         else {
1619             result = baseValue.get(callFrame, i);
1620             if (!isJSString(baseValue))
1621                 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
1622         }
1623     } else if (isName(subscript))
1624         result = baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName());
1625     else {
1626         Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1627         result = baseValue.get(callFrame, property);
1628     }
1629     
1630     CHECK_FOR_EXCEPTION_AT_END();
1631     return JSValue::encode(result);
1632 }
1633
1634 static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value)
1635 {
1636     if (LIKELY(subscript.isUInt32())) {
1637         uint32_t i = subscript.asUInt32();
1638         if (baseValue.isObject()) {
1639             JSObject* object = asObject(baseValue);
1640             if (object->canSetIndexQuickly(i))
1641                 object->setIndexQuickly(callFrame->vm(), i, value);
1642             else
1643                 object->methodTable()->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
1644         } else
1645             baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
1646     } else if (isName(subscript)) {
1647         PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1648         baseValue.put(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
1649     } else {
1650         Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1651         if (!callFrame->vm().exception()) { // Don't put to an object if toString threw an exception.
1652             PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1653             baseValue.put(callFrame, property, value, slot);
1654         }
1655     }
1656 }
1657
1658 DEFINE_STUB_FUNCTION(void, op_put_by_val)
1659 {
1660     STUB_INIT_STACK_FRAME(stackFrame);
1661
1662     CallFrame* callFrame = stackFrame.callFrame;
1663
1664     JSValue baseValue = stackFrame.args[0].jsValue();
1665     JSValue subscript = stackFrame.args[1].jsValue();
1666     JSValue value = stackFrame.args[2].jsValue();
1667     
1668     if (baseValue.isObject() && subscript.isInt32()) {
1669         // See if it's worth optimizing at all.
1670         JSObject* object = asObject(baseValue);
1671         bool didOptimize = false;
1672
1673         unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
1674         ASSERT(bytecodeOffset);
1675         ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
1676         ASSERT(!byValInfo.stubRoutine);
1677         
1678         if (hasOptimizableIndexing(object->structure())) {
1679             // Attempt to optimize.
1680             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure());
1681             if (arrayMode != byValInfo.arrayMode) {
1682                 JIT::compilePutByVal(&callFrame->vm(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode);
1683                 didOptimize = true;
1684             }
1685         }
1686
1687         if (!didOptimize) {
1688             // If we take slow path more than 10 times without patching then make sure we
1689             // never make that mistake again. Or, if we failed to patch and we have some object
1690             // that intercepts indexed get, then don't even wait until 10 times. For cases
1691             // where we see non-index-intercepting objects, this gives 10 iterations worth of
1692             // opportunity for us to observe that the get_by_val may be polymorphic.
1693             if (++byValInfo.slowPathCount >= 10
1694                 || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1695                 // Don't ever try to optimize.
1696                 RepatchBuffer repatchBuffer(callFrame->codeBlock());
1697                 repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_generic));
1698             }
1699         }
1700     }
1701     
1702     putByVal(callFrame, baseValue, subscript, value);
1703
1704     CHECK_FOR_EXCEPTION_AT_END();
1705 }
1706
1707 DEFINE_STUB_FUNCTION(void, op_put_by_val_generic)
1708 {
1709     STUB_INIT_STACK_FRAME(stackFrame);
1710
1711     CallFrame* callFrame = stackFrame.callFrame;
1712
1713     JSValue baseValue = stackFrame.args[0].jsValue();
1714     JSValue subscript = stackFrame.args[1].jsValue();
1715     JSValue value = stackFrame.args[2].jsValue();
1716     
1717     putByVal(callFrame, baseValue, subscript, value);
1718
1719     CHECK_FOR_EXCEPTION_AT_END();
1720 }
1721
1722 DEFINE_STUB_FUNCTION(void*, op_load_varargs)
1723 {
1724     STUB_INIT_STACK_FRAME(stackFrame);
1725
1726     CallFrame* callFrame = stackFrame.callFrame;
1727     JSStack* stack = stackFrame.stack;
1728     JSValue thisValue = stackFrame.args[0].jsValue();
1729     JSValue arguments = stackFrame.args[1].jsValue();
1730     int firstFreeRegister = stackFrame.args[2].int32();
1731
1732     CallFrame* newCallFrame = loadVarargs(callFrame, stack, thisValue, arguments, firstFreeRegister);
1733     if (!newCallFrame)
1734         VM_THROW_EXCEPTION();
1735     return newCallFrame;
1736 }
1737
1738 DEFINE_STUB_FUNCTION(int, op_jless)
1739 {
1740     STUB_INIT_STACK_FRAME(stackFrame);
1741
1742     JSValue src1 = stackFrame.args[0].jsValue();
1743     JSValue src2 = stackFrame.args[1].jsValue();
1744     CallFrame* callFrame = stackFrame.callFrame;
1745
1746     bool result = jsLess<true>(callFrame, src1, src2);
1747     CHECK_FOR_EXCEPTION_AT_END();
1748     return result;
1749 }
1750
1751 DEFINE_STUB_FUNCTION(int, op_jlesseq)
1752 {
1753     STUB_INIT_STACK_FRAME(stackFrame);
1754
1755     JSValue src1 = stackFrame.args[0].jsValue();
1756     JSValue src2 = stackFrame.args[1].jsValue();
1757     CallFrame* callFrame = stackFrame.callFrame;
1758
1759     bool result = jsLessEq<true>(callFrame, src1, src2);
1760     CHECK_FOR_EXCEPTION_AT_END();
1761     return result;
1762 }
1763
1764 DEFINE_STUB_FUNCTION(int, op_jgreater)
1765 {
1766     STUB_INIT_STACK_FRAME(stackFrame);
1767
1768     JSValue src1 = stackFrame.args[0].jsValue();
1769     JSValue src2 = stackFrame.args[1].jsValue();
1770     CallFrame* callFrame = stackFrame.callFrame;
1771
1772     bool result = jsLess<false>(callFrame, src2, src1);
1773     CHECK_FOR_EXCEPTION_AT_END();
1774     return result;
1775 }
1776
1777 DEFINE_STUB_FUNCTION(int, op_jgreatereq)
1778 {
1779     STUB_INIT_STACK_FRAME(stackFrame);
1780
1781     JSValue src1 = stackFrame.args[0].jsValue();
1782     JSValue src2 = stackFrame.args[1].jsValue();
1783     CallFrame* callFrame = stackFrame.callFrame;
1784
1785     bool result = jsLessEq<false>(callFrame, src2, src1);
1786     CHECK_FOR_EXCEPTION_AT_END();
1787     return result;
1788 }
1789
1790 DEFINE_STUB_FUNCTION(int, op_jtrue)
1791 {
1792     STUB_INIT_STACK_FRAME(stackFrame);
1793
1794     JSValue src1 = stackFrame.args[0].jsValue();
1795
1796     bool result = src1.toBoolean(stackFrame.callFrame);
1797     CHECK_FOR_EXCEPTION_AT_END();
1798     return result;
1799 }
1800
1801 DEFINE_STUB_FUNCTION(int, op_eq)
1802 {
1803     STUB_INIT_STACK_FRAME(stackFrame);
1804
1805     JSValue src1 = stackFrame.args[0].jsValue();
1806     JSValue src2 = stackFrame.args[1].jsValue();
1807
1808 #if USE(JSVALUE32_64)
1809     start:
1810     if (src2.isUndefined()) {
1811         return src1.isNull() || 
1812                (src1.isCell() && src1.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject()))
1813                || src1.isUndefined();
1814     }
1815     
1816     if (src2.isNull()) {
1817         return src1.isUndefined() || 
1818                (src1.isCell() && src1.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject()))
1819                || src1.isNull();
1820     }
1821
1822     if (src1.isInt32()) {
1823         if (src2.isDouble())
1824             return src1.asInt32() == src2.asDouble();
1825         double d = src2.toNumber(stackFrame.callFrame);
1826         CHECK_FOR_EXCEPTION();
1827         return src1.asInt32() == d;
1828     }
1829
1830     if (src1.isDouble()) {
1831         if (src2.isInt32())
1832             return src1.asDouble() == src2.asInt32();
1833         double d = src2.toNumber(stackFrame.callFrame);
1834         CHECK_FOR_EXCEPTION();
1835         return src1.asDouble() == d;
1836     }
1837
1838     if (src1.isTrue()) {
1839         if (src2.isFalse())
1840             return false;
1841         double d = src2.toNumber(stackFrame.callFrame);
1842         CHECK_FOR_EXCEPTION();
1843         return d == 1.0;
1844     }
1845
1846     if (src1.isFalse()) {
1847         if (src2.isTrue())
1848             return false;
1849         double d = src2.toNumber(stackFrame.callFrame);
1850         CHECK_FOR_EXCEPTION();
1851         return d == 0.0;
1852     }
1853     
1854     if (src1.isUndefined())
1855         return src2.isCell() && src2.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject());
1856     
1857     if (src1.isNull())
1858         return src2.isCell() && src2.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject());
1859
1860     JSCell* cell1 = src1.asCell();
1861
1862     if (cell1->isString()) {
1863         if (src2.isInt32())
1864             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32();
1865             
1866         if (src2.isDouble())
1867             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble();
1868
1869         if (src2.isTrue())
1870             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0;
1871
1872         if (src2.isFalse())
1873             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0;
1874
1875         JSCell* cell2 = src2.asCell();
1876         if (cell2->isString())
1877             return jsCast<JSString*>(cell1)->value(stackFrame.callFrame) == jsCast<JSString*>(cell2)->value(stackFrame.callFrame);
1878
1879         src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame);
1880         CHECK_FOR_EXCEPTION();
1881         goto start;
1882     }
1883
1884     if (src2.isObject())
1885         return asObject(cell1) == asObject(src2);
1886     src1 = asObject(cell1)->toPrimitive(stackFrame.callFrame);
1887     CHECK_FOR_EXCEPTION();
1888     goto start;
1889     
1890 #else // USE(JSVALUE32_64)
1891     CallFrame* callFrame = stackFrame.callFrame;
1892     
1893     bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2);
1894     CHECK_FOR_EXCEPTION_AT_END();
1895     return result;
1896 #endif // USE(JSVALUE32_64)
1897 }
1898
1899 DEFINE_STUB_FUNCTION(int, op_eq_strings)
1900 {
1901 #if USE(JSVALUE32_64)
1902     STUB_INIT_STACK_FRAME(stackFrame);
1903
1904     JSString* string1 = stackFrame.args[0].jsString();
1905     JSString* string2 = stackFrame.args[1].jsString();
1906
1907     ASSERT(string1->isString());
1908     ASSERT(string2->isString());
1909     return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame);
1910 #else
1911     UNUSED_PARAM(args);
1912     RELEASE_ASSERT_NOT_REACHED();
1913     return 0;
1914 #endif
1915 }
1916
1917 DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
1918 {
1919     STUB_INIT_STACK_FRAME(stackFrame);
1920     CallFrame* callFrame = stackFrame.callFrame;
1921
1922     FunctionExecutable* function = stackFrame.args[0].function();
1923     JSFunction* func = JSFunction::create(callFrame, function, callFrame->scope());
1924     ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister()).jsValue());
1925
1926     return func;
1927 }
1928
1929 DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp)
1930 {
1931     STUB_INIT_STACK_FRAME(stackFrame);
1932
1933     CallFrame* callFrame = stackFrame.callFrame;
1934
1935     RegExp* regExp = stackFrame.args[0].regExp();
1936     if (!regExp->isValid()) {
1937         stackFrame.vm->throwException(callFrame, createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor."));
1938         VM_THROW_EXCEPTION();
1939     }
1940
1941     return RegExpObject::create(*stackFrame.vm, stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), regExp);
1942 }
1943
1944 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
1945 {
1946     STUB_INIT_STACK_FRAME(stackFrame);
1947
1948     CallFrame* callFrame = stackFrame.callFrame;
1949     CallFrame* callerFrame = callFrame->callerFrame();
1950     ASSERT(callFrame->callerFrame()->codeBlock()->codeType() != FunctionCode
1951         || !callFrame->callerFrame()->codeBlock()->needsFullScopeChain()
1952         || callFrame->callerFrame()->uncheckedR(callFrame->callerFrame()->codeBlock()->activationRegister()).jsValue());
1953
1954     callFrame->setScope(callerFrame->scope());
1955     callFrame->setReturnPC(static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()));
1956     callFrame->setCodeBlock(0);
1957
1958     if (!isHostFunction(callFrame->calleeAsValue(), globalFuncEval))
1959         return JSValue::encode(JSValue());
1960
1961     JSValue result = eval(callFrame);
1962     if (stackFrame.vm->exception())
1963         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1964
1965     return JSValue::encode(result);
1966 }
1967
1968 DEFINE_STUB_FUNCTION(void*, op_throw)
1969 {
1970     STUB_INIT_STACK_FRAME(stackFrame);
1971     stackFrame.vm->throwException(stackFrame.callFrame, stackFrame.args[0].jsValue()); 
1972     ExceptionHandler handler = jitThrow(stackFrame.vm, stackFrame.callFrame, stackFrame.args[0].jsValue(), STUB_RETURN_ADDRESS);
1973     STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1974     return handler.callFrame;
1975 }
1976
1977 DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
1978 {
1979     STUB_INIT_STACK_FRAME(stackFrame);
1980
1981     CallFrame* callFrame = stackFrame.callFrame;
1982     JSObject* o = stackFrame.args[0].jsObject();
1983     Structure* structure = o->structure();
1984     JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
1985     if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
1986         jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
1987     return jsPropertyNameIterator;
1988 }
1989
1990 DEFINE_STUB_FUNCTION(int, has_property)
1991 {
1992     STUB_INIT_STACK_FRAME(stackFrame);
1993
1994     JSObject* base = stackFrame.args[0].jsObject();
1995     JSString* property = stackFrame.args[1].jsString();
1996     int result = base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame)));
1997     CHECK_FOR_EXCEPTION_AT_END();
1998     return result;
1999 }
2000
2001 DEFINE_STUB_FUNCTION(void, op_push_with_scope)
2002 {
2003     STUB_INIT_STACK_FRAME(stackFrame);
2004
2005     JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame);
2006     CHECK_FOR_EXCEPTION_VOID();
2007     stackFrame.callFrame->setScope(JSWithScope::create(stackFrame.callFrame, o));
2008 }
2009
2010 DEFINE_STUB_FUNCTION(void, op_pop_scope)
2011 {
2012     STUB_INIT_STACK_FRAME(stackFrame);
2013
2014     stackFrame.callFrame->setScope(stackFrame.callFrame->scope()->next());
2015 }
2016
2017 DEFINE_STUB_FUNCTION(void, op_push_name_scope)
2018 {
2019     STUB_INIT_STACK_FRAME(stackFrame);
2020
2021     JSNameScope* scope = JSNameScope::create(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), stackFrame.args[2].int32());
2022
2023     CallFrame* callFrame = stackFrame.callFrame;
2024     callFrame->setScope(scope);
2025 }
2026
2027 DEFINE_STUB_FUNCTION(void, op_put_by_index)
2028 {
2029     STUB_INIT_STACK_FRAME(stackFrame);
2030
2031     CallFrame* callFrame = stackFrame.callFrame;
2032     unsigned property = stackFrame.args[1].int32();
2033
2034     JSValue arrayValue = stackFrame.args[0].jsValue();
2035     ASSERT(isJSArray(arrayValue));
2036     asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue());
2037 }
2038
2039 DEFINE_STUB_FUNCTION(void*, op_switch_imm)
2040 {
2041     STUB_INIT_STACK_FRAME(stackFrame);
2042
2043     JSValue scrutinee = stackFrame.args[0].jsValue();
2044     unsigned tableIndex = stackFrame.args[1].int32();
2045     CallFrame* callFrame = stackFrame.callFrame;
2046     CodeBlock* codeBlock = callFrame->codeBlock();
2047
2048     if (scrutinee.isInt32())
2049         return codeBlock->switchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress();
2050     if (scrutinee.isDouble() && scrutinee.asDouble() == static_cast<int32_t>(scrutinee.asDouble()))
2051         return codeBlock->switchJumpTable(tableIndex).ctiForValue(static_cast<int32_t>(scrutinee.asDouble())).executableAddress();
2052     return codeBlock->switchJumpTable(tableIndex).ctiDefault.executableAddress();
2053 }
2054
2055 DEFINE_STUB_FUNCTION(void*, op_switch_char)
2056 {
2057     STUB_INIT_STACK_FRAME(stackFrame);
2058
2059     JSValue scrutinee = stackFrame.args[0].jsValue();
2060     unsigned tableIndex = stackFrame.args[1].int32();
2061     CallFrame* callFrame = stackFrame.callFrame;
2062     CodeBlock* codeBlock = callFrame->codeBlock();
2063
2064     void* result = codeBlock->switchJumpTable(tableIndex).ctiDefault.executableAddress();
2065
2066     if (scrutinee.isString()) {
2067         StringImpl* value = asString(scrutinee)->value(callFrame).impl();
2068         if (value->length() == 1)
2069             result = codeBlock->switchJumpTable(tableIndex).ctiForValue((*value)[0]).executableAddress();
2070     }
2071
2072     CHECK_FOR_EXCEPTION_AT_END();
2073     return result;
2074 }
2075
2076 DEFINE_STUB_FUNCTION(void*, op_switch_string)
2077 {
2078     STUB_INIT_STACK_FRAME(stackFrame);
2079
2080     JSValue scrutinee = stackFrame.args[0].jsValue();
2081     unsigned tableIndex = stackFrame.args[1].int32();
2082     CallFrame* callFrame = stackFrame.callFrame;
2083     CodeBlock* codeBlock = callFrame->codeBlock();
2084
2085     void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
2086
2087     if (scrutinee.isString()) {
2088         StringImpl* value = asString(scrutinee)->value(callFrame).impl();
2089         result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
2090     }
2091
2092     CHECK_FOR_EXCEPTION_AT_END();
2093     return result;
2094 }
2095
2096 DEFINE_STUB_FUNCTION(void, op_put_getter_setter)
2097 {
2098     STUB_INIT_STACK_FRAME(stackFrame);
2099
2100     CallFrame* callFrame = stackFrame.callFrame;
2101
2102     ASSERT(stackFrame.args[0].jsValue().isObject());
2103     JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
2104
2105     GetterSetter* accessor = GetterSetter::create(callFrame);
2106
2107     JSValue getter = stackFrame.args[2].jsValue();
2108     JSValue setter = stackFrame.args[3].jsValue();
2109     ASSERT(getter.isObject() || getter.isUndefined());
2110     ASSERT(setter.isObject() || setter.isUndefined());
2111     ASSERT(getter.isObject() || setter.isObject());
2112
2113     if (!getter.isUndefined())
2114         accessor->setGetter(callFrame->vm(), asObject(getter));
2115     if (!setter.isUndefined())
2116         accessor->setSetter(callFrame->vm(), asObject(setter));
2117     baseObj->putDirectAccessor(callFrame, stackFrame.args[1].identifier(), accessor, Accessor);
2118 }
2119
2120 DEFINE_STUB_FUNCTION(void, op_throw_static_error)
2121 {
2122     STUB_INIT_STACK_FRAME(stackFrame);
2123
2124     CallFrame* callFrame = stackFrame.callFrame;
2125     String message = errorDescriptionForValue(callFrame, stackFrame.args[0].jsValue())->value(callFrame);
2126     if (stackFrame.args[1].asInt32)
2127         stackFrame.vm->throwException(callFrame, createReferenceError(callFrame, message));
2128     else
2129         stackFrame.vm->throwException(callFrame, createTypeError(callFrame, message));
2130     VM_THROW_EXCEPTION_AT_END();
2131 }
2132
2133 DEFINE_STUB_FUNCTION(void, op_debug)
2134 {
2135     STUB_INIT_STACK_FRAME(stackFrame);
2136
2137     CallFrame* callFrame = stackFrame.callFrame;
2138
2139     int debugHookID = stackFrame.args[0].int32();
2140     int firstLine = stackFrame.args[1].int32();
2141     int lastLine = stackFrame.args[2].int32();
2142     int column = stackFrame.args[3].int32();
2143
2144     stackFrame.vm->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column);
2145 }
2146
2147 DEFINE_STUB_FUNCTION(void*, vm_throw)
2148 {
2149     STUB_INIT_STACK_FRAME(stackFrame);
2150     VM* vm = stackFrame.vm;
2151     ExceptionHandler handler = jitThrow(vm, stackFrame.callFrame, vm->exception(), vm->exceptionLocation);
2152     STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
2153     return handler.callFrame;
2154 }
2155
2156 #if USE(JSVALUE32_64)
2157 EncodedExceptionHandler JIT_STUB cti_vm_handle_exception(CallFrame* callFrame)
2158 {
2159     ASSERT(!callFrame->hasHostCallFrameFlag());
2160     if (!callFrame) {
2161         // The entire stack has already been unwound. Nothing more to handle.
2162         return encode(uncaughtExceptionHandler());
2163     }
2164
2165     VM* vm = callFrame->codeBlock()->vm();
2166     vm->topCallFrame = callFrame;
2167     return encode(jitThrowNew(vm, callFrame, vm->exception()));
2168 }
2169 #else
2170 ExceptionHandler JIT_STUB cti_vm_handle_exception(CallFrame* callFrame)
2171 {
2172     ASSERT(!callFrame->hasHostCallFrameFlag());
2173     if (!callFrame) {
2174         // The entire stack has already been unwound. Nothing more to handle.
2175         return uncaughtExceptionHandler();
2176     }
2177
2178     VM* vm = callFrame->codeBlock()->vm();
2179     vm->topCallFrame = callFrame;
2180     return jitThrowNew(vm, callFrame, vm->exception());
2181 }
2182 #endif
2183
2184 DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
2185 {
2186     STUB_INIT_STACK_FRAME(stackFrame);
2187
2188     CallFrame* callFrame = stackFrame.callFrame;
2189     return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
2190 }
2191
2192 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_scope)
2193 {
2194     STUB_INIT_STACK_FRAME(stackFrame);
2195     ExecState* exec = stackFrame.callFrame;
2196     Instruction* pc = stackFrame.args[0].pc();
2197
2198     const Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
2199     return JSValue::encode(JSScope::resolve(exec, exec->scope(), ident));
2200 }
2201
2202 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_from_scope)
2203 {
2204     STUB_INIT_STACK_FRAME(stackFrame);
2205     ExecState* exec = stackFrame.callFrame;
2206     Instruction* pc = stackFrame.args[0].pc();
2207
2208     const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
2209     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[2].u.operand).jsValue());
2210     ResolveModeAndType modeAndType(pc[4].u.operand);
2211
2212     PropertySlot slot(scope);
2213     if (!scope->getPropertySlot(exec, ident, slot)) {
2214         if (modeAndType.mode() == ThrowIfNotFound) {
2215             exec->vm().throwException(exec, createUndefinedVariableError(exec, ident));
2216             VM_THROW_EXCEPTION();
2217         }
2218         return JSValue::encode(jsUndefined());
2219     }
2220
2221     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
2222     if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure()->propertyAccessesAreCacheable()) {
2223         if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
2224             CodeBlock* codeBlock = exec->codeBlock();
2225             ConcurrentJITLocker locker(codeBlock->m_lock);
2226             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
2227             pc[6].u.operand = slot.cachedOffset();
2228         }
2229     }
2230
2231     return JSValue::encode(slot.getValue(exec, ident));
2232 }
2233
2234 DEFINE_STUB_FUNCTION(void, op_put_to_scope)
2235 {
2236     STUB_INIT_STACK_FRAME(stackFrame);
2237     ExecState* exec = stackFrame.callFrame;
2238     Instruction* pc = stackFrame.args[0].pc();
2239
2240     CodeBlock* codeBlock = exec->codeBlock();
2241     const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
2242     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[1].u.operand).jsValue());
2243     JSValue value = exec->r(pc[3].u.operand).jsValue();
2244     ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
2245
2246     if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident)) {
2247         exec->vm().throwException(exec, createUndefinedVariableError(exec, ident));
2248         VM_THROW_EXCEPTION_AT_END();
2249         return;
2250     }
2251
2252     PutPropertySlot slot(codeBlock->isStrictMode());
2253     scope->methodTable()->put(scope, exec, ident, value, slot);
2254     
2255     if (exec->vm().exception()) {
2256         VM_THROW_EXCEPTION_AT_END();
2257         return;
2258     }
2259
2260     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
2261     if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
2262         if (slot.isCacheable() && slot.base() == scope && scope->structure()->propertyAccessesAreCacheable()) {
2263             ConcurrentJITLocker locker(codeBlock->m_lock);
2264             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
2265             pc[6].u.operand = slot.cachedOffset();
2266         }
2267     }
2268 }
2269
2270 } // namespace JSC
2271
2272 #endif // ENABLE(JIT)