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