Changeset 41100 in webkit for trunk/JavaScriptCore/runtime


Ignore:
Timestamp:
Feb 19, 2009, 10:04:21 PM (16 years ago)
Author:
[email protected]
Message:

2009-02-19 Geoffrey Garen <[email protected]>

Reviewed by Gavin Barraclough.


First step in splitting JIT functionality out of the Interpreter class:
Created JITStubs.h/.cpp, and moved Interpreter::cti_* into JITStubs.cpp.


Functions that the Interpreter and JITStubs share moved to Operations.h/.cpp.

  • GNUmakefile.am:
  • JavaScriptCore.pri:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • interpreter/Interpreter.cpp: (JSC::Interpreter::resolveBase): (JSC::Interpreter::checkTimeout): (JSC::Interpreter::privateExecute):
  • interpreter/Interpreter.h:
  • jit/JITStubs.cpp: Copied from interpreter/Interpreter.cpp. (JSC::Interpreter::cti_op_resolve_base):
  • jit/JITStubs.h: Copied from interpreter/Interpreter.h.
  • runtime/Operations.cpp: (JSC::jsAddSlowCase): (JSC::jsTypeStringForValue): (JSC::jsIsObjectType): (JSC::jsIsFunctionType):
  • runtime/Operations.h: (JSC::jsLess): (JSC::jsLessEq): (JSC::jsAdd): (JSC::cachePrototypeChain): (JSC::countPrototypeChainEntriesAndCheckForProxies): (JSC::resolveBase):
Location:
trunk/JavaScriptCore/runtime
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/Operations.cpp

    r39851 r41100  
    5353}
    5454
     55NEVER_INLINE JSValuePtr jsAddSlowCase(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
     56{
     57    // exception for the Date exception in defaultValue()
     58    JSValuePtr p1 = v1.toPrimitive(callFrame);
     59    JSValuePtr p2 = v2.toPrimitive(callFrame);
     60
     61    if (p1.isString() || p2.isString()) {
     62        RefPtr<UString::Rep> value = concatenate(p1.toString(callFrame).rep(), p2.toString(callFrame).rep());
     63        if (!value)
     64            return throwOutOfMemoryError(callFrame);
     65        return jsString(callFrame, value.release());
     66    }
     67
     68    return jsNumber(callFrame, p1.toNumber(callFrame) + p2.toNumber(callFrame));
     69}
     70
     71JSValuePtr jsTypeStringForValue(CallFrame* callFrame, JSValuePtr v)
     72{
     73    if (v.isUndefined())
     74        return jsNontrivialString(callFrame, "undefined");
     75    if (v.isBoolean())
     76        return jsNontrivialString(callFrame, "boolean");
     77    if (v.isNumber())
     78        return jsNontrivialString(callFrame, "number");
     79    if (v.isString())
     80        return jsNontrivialString(callFrame, "string");
     81    if (v.isObject()) {
     82        // Return "undefined" for objects that should be treated
     83        // as null when doing comparisons.
     84        if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
     85            return jsNontrivialString(callFrame, "undefined");
     86        CallData callData;
     87        if (asObject(v)->getCallData(callData) != CallTypeNone)
     88            return jsNontrivialString(callFrame, "function");
     89    }
     90    return jsNontrivialString(callFrame, "object");
     91}
     92
     93bool jsIsObjectType(JSValuePtr v)
     94{
     95    if (!v.isCell())
     96        return v.isNull();
     97
     98    JSType type = asCell(v)->structure()->typeInfo().type();
     99    if (type == NumberType || type == StringType)
     100        return false;
     101    if (type == ObjectType) {
     102        if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
     103            return false;
     104        CallData callData;
     105        if (asObject(v)->getCallData(callData) != CallTypeNone)
     106            return false;
     107    }
     108    return true;
     109}
     110
     111bool jsIsFunctionType(JSValuePtr v)
     112{
     113    if (v.isObject()) {
     114        CallData callData;
     115        if (asObject(v)->getCallData(callData) != CallTypeNone)
     116            return true;
     117    }
     118    return false;
     119}
     120
    55121} // namespace JSC
  • trunk/JavaScriptCore/runtime/Operations.h

    r40046 r41100  
    2323#define Operations_h
    2424
     25#include "Interpreter.h"
    2526#include "JSImmediate.h"
    2627#include "JSNumberCell.h"
     
    2829
    2930namespace JSC {
     31
     32    NEVER_INLINE JSValuePtr throwOutOfMemoryError(ExecState*);
     33    NEVER_INLINE JSValuePtr jsAddSlowCase(CallFrame*, JSValuePtr, JSValuePtr);
     34    JSValuePtr jsTypeStringForValue(CallFrame*, JSValuePtr);
     35    bool jsIsObjectType(JSValuePtr);
     36    bool jsIsFunctionType(JSValuePtr);
    3037
    3138    // ECMA 11.9.3
     
    130137    }
    131138
    132     JSValuePtr throwOutOfMemoryError(ExecState*);
    133 
    134 }
    135 #endif
     139    inline bool jsLess(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
     140    {
     141        if (JSValuePtr::areBothInt32Fast(v1, v2))
     142            return v1.getInt32Fast() < v2.getInt32Fast();
     143
     144        double n1;
     145        double n2;
     146        if (v1.getNumber(n1) && v2.getNumber(n2))
     147            return n1 < n2;
     148
     149        Interpreter* interpreter = callFrame->interpreter();
     150        if (interpreter->isJSString(v1) && interpreter->isJSString(v2))
     151            return asString(v1)->value() < asString(v2)->value();
     152
     153        JSValuePtr p1;
     154        JSValuePtr p2;
     155        bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
     156        bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
     157
     158        if (wasNotString1 | wasNotString2)
     159            return n1 < n2;
     160
     161        return asString(p1)->value() < asString(p2)->value();
     162    }
     163
     164    inline bool jsLessEq(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
     165    {
     166        if (JSValuePtr::areBothInt32Fast(v1, v2))
     167            return v1.getInt32Fast() <= v2.getInt32Fast();
     168
     169        double n1;
     170        double n2;
     171        if (v1.getNumber(n1) && v2.getNumber(n2))
     172            return n1 <= n2;
     173
     174        Interpreter* interpreter = callFrame->interpreter();
     175        if (interpreter->isJSString(v1) && interpreter->isJSString(v2))
     176            return !(asString(v2)->value() < asString(v1)->value());
     177
     178        JSValuePtr p1;
     179        JSValuePtr p2;
     180        bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
     181        bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
     182
     183        if (wasNotString1 | wasNotString2)
     184            return n1 <= n2;
     185
     186        return !(asString(p2)->value() < asString(p1)->value());
     187    }
     188
     189    // Fast-path choices here are based on frequency data from SunSpider:
     190    //    <times> Add case: <t1> <t2>
     191    //    ---------------------------
     192    //    5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
     193    //    247412  Add case: 5 5
     194    //    20900   Add case: 5 6
     195    //    13962   Add case: 5 3
     196    //    4000    Add case: 3 5
     197
     198    ALWAYS_INLINE JSValuePtr jsAdd(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
     199    {
     200        double left;
     201        double right = 0.0;
     202
     203        bool rightIsNumber = v2.getNumber(right);
     204        if (rightIsNumber && v1.getNumber(left))
     205            return jsNumber(callFrame, left + right);
     206       
     207        bool leftIsString = v1.isString();
     208        if (leftIsString && v2.isString()) {
     209            RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep());
     210            if (!value)
     211                return throwOutOfMemoryError(callFrame);
     212            return jsString(callFrame, value.release());
     213        }
     214
     215        if (rightIsNumber & leftIsString) {
     216            RefPtr<UString::Rep> value = v2.isInt32Fast() ?
     217                concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) :
     218                concatenate(asString(v1)->value().rep(), right);
     219
     220            if (!value)
     221                return throwOutOfMemoryError(callFrame);
     222            return jsString(callFrame, value.release());
     223        }
     224
     225        // All other cases are pretty uncommon
     226        return jsAddSlowCase(callFrame, v1, v2);
     227    }
     228
     229    inline StructureChain* cachePrototypeChain(CallFrame* callFrame, Structure* structure)
     230    {
     231        JSValuePtr prototype = structure->prototypeForLookup(callFrame);
     232        if (!prototype.isCell())
     233            return 0;
     234        RefPtr<StructureChain> chain = StructureChain::create(asObject(prototype)->structure());
     235        structure->setCachedPrototypeChain(chain.release());
     236        return structure->cachedPrototypeChain();
     237    }
     238
     239    inline size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValuePtr baseValue, const PropertySlot& slot)
     240    {
     241        JSCell* cell = asCell(baseValue);
     242        size_t count = 0;
     243
     244        while (slot.slotBase() != cell) {
     245            JSValuePtr v = cell->structure()->prototypeForLookup(callFrame);
     246
     247            // If we didn't find slotBase in baseValue's prototype chain, then baseValue
     248            // must be a proxy for another object.
     249
     250            if (v.isNull())
     251                return 0;
     252
     253            cell = asCell(v);
     254
     255            // Since we're accessing a prototype in a loop, it's a good bet that it
     256            // should not be treated as a dictionary.
     257            if (cell->structure()->isDictionary()) {
     258                RefPtr<Structure> transition = Structure::fromDictionaryTransition(cell->structure());
     259                asObject(cell)->setStructure(transition.release());
     260                cell->structure()->setCachedPrototypeChain(0);
     261            }
     262
     263            ++count;
     264        }
     265       
     266        ASSERT(count);
     267        return count;
     268    }
     269
     270    ALWAYS_INLINE JSValuePtr resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain)
     271    {
     272        ScopeChainIterator iter = scopeChain->begin();
     273        ScopeChainIterator next = iter;
     274        ++next;
     275        ScopeChainIterator end = scopeChain->end();
     276        ASSERT(iter != end);
     277
     278        PropertySlot slot;
     279        JSObject* base;
     280        while (true) {
     281            base = *iter;
     282            if (next == end || base->getPropertySlot(callFrame, property, slot))
     283                return base;
     284
     285            iter = next;
     286            ++next;
     287        }
     288
     289        ASSERT_NOT_REACHED();
     290        return noValue();
     291    }
     292
     293} // namespace JSC
     294
     295#endif // Operations_h
Note: See TracChangeset for help on using the changeset viewer.