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