Changeset 33393 in webkit


Ignore:
Timestamp:
May 13, 2008 2:50:55 PM (16 years ago)
Author:
oliver@apple.com
Message:

Bug 18752: SQUIRRELFISH: exceptions are not always handled by the vm
<https://bugs.webkit.org/show_bug.cgi?id=18752>

Reviewed by Darin

Replace old attempt at "branchless" exceptions as the extra information
being passed made gcc an unhappy compiler, replacing these custom toNumber
calls with ordinary toNumber logic (by relying on toNumber now preventing
side effects after an exception has been thrown) provided sufficient leeway
to add the additional checks for the remaining unchecked cases.

This leaves only toString conversions in certain contexts as possibly
misbehaving.

Location:
branches/squirrelfish
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • branches/squirrelfish/JavaScriptCore/ChangeLog

    r33386 r33393  
     12008-05-13  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Darin.
     4
     5        Bug 18752: SQUIRRELFISH: exceptions are not always handled by the vm
     6        <https://bugs.webkit.org/show_bug.cgi?id=18752>
     7
     8        Replace old attempt at "branchless" exceptions as the extra information
     9        being passed made gcc an unhappy compiler, replacing these custom toNumber
     10        calls with ordinary toNumber logic (by relying on toNumber now preventing
     11        side effects after an exception has been thrown) provided sufficient leeway
     12        to add the additional checks for the remaining unchecked cases.
     13
     14        This leaves only toString conversions in certain contexts as possibly
     15        misbehaving.
     16
     17        * VM/Machine.cpp:
     18        (KJS::jsAdd):
     19        (KJS::resolve):
     20        (KJS::resolveBaseAndProperty):
     21        (KJS::resolveBaseAndFunc):
     22        (KJS::Machine::privateExecute):
     23        * VM/Opcode.h:
     24        * kjs/value.h:
     25        (KJS::JSValue::safeGetNumber):
     26
    1272008-05-13  Geoffrey Garen  <ggaren@apple.com>
    228
  • branches/squirrelfish/JavaScriptCore/VM/Machine.cpp

    r33386 r33393  
    157157
    158158    if (bothTypes == ((NumberType << 3) | NumberType))
    159         return jsNumber(v1->toNumber(exec) + v2->toNumber(exec));
     159        return jsNumber(v1->uncheckedGetNumber() + v2->uncheckedGetNumber());
    160160    if (bothTypes == ((StringType << 3) | StringType)) {
    161161        UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
     
    210210        JSObject* o = *iter;
    211211        if (o->getPropertySlot(exec, ident, slot)) {
    212             r[dst].u.jsValue = slot.getValue(exec, o, ident);
     212            JSValue* result = slot.getValue(exec, o, ident);
    213213            exceptionValue = exec->exception();
    214             return !exceptionValue;
     214            if (exceptionValue)
     215                return false;
     216            r[dst].u.jsValue = result;
     217            return true;
    215218        }
    216219    } while (++iter != end);
     
    260263    do {
    261264        base = *iter;
    262         if (base->getPropertySlot(exec, ident, slot)) {           
     265        if (base->getPropertySlot(exec, ident, slot)) {
     266            JSValue* result = slot.getValue(exec, base, ident); 
     267            exceptionValue = exec->exception();
     268            if (exceptionValue)
     269                return false;
     270            r[propDst].u.jsValue = result;   
    263271            r[baseDst].u.jsValue = base;
    264             r[propDst].u.jsValue = slot.getValue(exec, base, ident);
    265272            return true;
    266273        }
     
    299306            // We also handle wrapper substitution for the global object at the same time.
    300307            JSObject* thisObj = base->toThisObject(exec);
     308            JSValue* result = slot.getValue(exec, base, ident);
     309            exceptionValue = exec->exception();
     310            if (exceptionValue)
     311                return false;
    301312           
    302313            r[baseDst].u.jsValue = thisObj;
    303             r[funcDst].u.jsValue = slot.getValue(exec, base, ident);
     314            r[funcDst].u.jsValue = result;
    304315            return true;
    305316        }
     
    738749        return 0;
    739750    }
    740    
    741     // Any pointer arithmetic to compensate for incrementing the vPC, currently
    742     // we only use for opcodes that perform a single increment of vPC.  As we
    743     // start applying the branch free exception logic to operands that increment
    744     // vPC by more than one Instruction we'll need to make this buffer larger.
    745     Instruction builtinThrow = getOpcode(op_builtin_throw);
    746     Instruction builtinThrowBuffer[] = { builtinThrow, builtinThrow };
     751
    747752    JSValue* exceptionValue = 0;
    748753    Instruction* handlerVPC = 0;
     
    909914        int src1 = (++vPC)->u.operand;
    910915        int src2 = (++vPC)->u.operand;
    911         r[dst].u.jsValue = jsBoolean(jsLess(exec, r[src1].u.jsValue, r[src2].u.jsValue));
     916        JSValue* result = jsBoolean(jsLess(exec, r[src1].u.jsValue, r[src2].u.jsValue));
     917        VM_CHECK_EXCEPTION();
     918        r[dst].u.jsValue = result;
    912919
    913920        ++vPC;
     
    924931        int src1 = (++vPC)->u.operand;
    925932        int src2 = (++vPC)->u.operand;
    926         r[dst].u.jsValue = jsBoolean(jsLessEq(exec, r[src1].u.jsValue, r[src2].u.jsValue));
     933        JSValue* result = jsBoolean(jsLessEq(exec, r[src1].u.jsValue, r[src2].u.jsValue));
     934        VM_CHECK_EXCEPTION();
     935        r[dst].u.jsValue = result;
    927936
    928937        ++vPC;
     
    936945        */
    937946        int srcDst = (++vPC)->u.operand;
    938         Instruction* target;
    939         double d = r[srcDst].u.jsValue->toNumber(exec, vPC, builtinThrowBuffer, target);
    940         r[srcDst].u.jsValue = jsNumber(d + 1);
    941        
    942         vPC = target + 1;
     947        JSValue* result = jsNumber(r[srcDst].u.jsValue->toNumber(exec) + 1);
     948        VM_CHECK_EXCEPTION();
     949        r[srcDst].u.jsValue = result;
     950       
     951        ++vPC;
    943952        NEXT_OPCODE;
    944953    }
     
    950959        */
    951960        int srcDst = (++vPC)->u.operand;
    952         Instruction* target;
    953         double d = r[srcDst].u.jsValue->toNumber(exec, vPC, builtinThrowBuffer, target);
    954         r[srcDst].u.jsValue = jsNumber(d - 1);
    955        
    956         vPC = target + 1;
     961        JSValue* result = jsNumber(r[srcDst].u.jsValue->toNumber(exec) - 1);
     962        VM_CHECK_EXCEPTION();
     963        r[srcDst].u.jsValue = result;
     964
     965        ++vPC;
    957966        NEXT_OPCODE;
    958967    }
     
    966975        int dst = (++vPC)->u.operand;
    967976        int srcDst = (++vPC)->u.operand;
    968         r[dst].u.jsValue = r[srcDst].u.jsValue->toJSNumber(exec);
    969         r[srcDst].u.jsValue = jsNumber(r[dst].u.jsValue->toNumber(exec) + 1);
     977        JSValue* number = r[srcDst].u.jsValue->toJSNumber(exec);
     978        VM_CHECK_EXCEPTION();
     979
     980        r[dst].u.jsValue = number;
     981        r[srcDst].u.jsValue = jsNumber(number->uncheckedGetNumber() + 1);
    970982
    971983        ++vPC;
     
    981993        int dst = (++vPC)->u.operand;
    982994        int srcDst = (++vPC)->u.operand;
    983         r[dst].u.jsValue = r[srcDst].u.jsValue->toJSNumber(exec);
    984         r[srcDst].u.jsValue = jsNumber(r[dst].u.jsValue->toNumber(exec) - 1);
     995        JSValue* number = r[srcDst].u.jsValue->toJSNumber(exec);
     996        VM_CHECK_EXCEPTION();
     997
     998        r[dst].u.jsValue = number;
     999        r[srcDst].u.jsValue = jsNumber(number->uncheckedGetNumber() - 1);
    9851000
    9861001        ++vPC;
     
    9951010        int dst = (++vPC)->u.operand;
    9961011        int src = (++vPC)->u.operand;
    997         r[dst].u.jsValue = r[src].u.jsValue->toJSNumber(exec);
     1012        JSValue* result = r[src].u.jsValue->toJSNumber(exec);
     1013        VM_CHECK_EXCEPTION();
     1014
     1015        r[dst].u.jsValue = result;
    9981016
    9991017        ++vPC;
     
    10081026        int dst = (++vPC)->u.operand;
    10091027        int src = (++vPC)->u.operand;
    1010        
    1011         Instruction* target;
    1012         double d = r[src].u.jsValue->toNumber(exec, vPC, builtinThrowBuffer, target);
    1013         r[dst].u.jsValue = jsNumber(-d);
    1014 
    1015         vPC = target + 1;
     1028        JSValue* result = jsNumber(-r[src].u.jsValue->toNumber(exec));
     1029        VM_CHECK_EXCEPTION();
     1030        r[dst].u.jsValue = result;
     1031
     1032        ++vPC;
    10161033        NEXT_OPCODE;
    10171034    }
     
    10261043        int src1 = (++vPC)->u.operand;
    10271044        int src2 = (++vPC)->u.operand;
    1028         r[dst].u.jsValue = jsAdd(exec, r[src1].u.jsValue, r[src2].u.jsValue);
    1029 
     1045        JSValue* result = jsAdd(exec, r[src1].u.jsValue, r[src2].u.jsValue);
     1046        VM_CHECK_EXCEPTION();
     1047        r[dst].u.jsValue = result;
    10301048        ++vPC;
    10311049        NEXT_OPCODE;
     
    10401058        int src1 = (++vPC)->u.operand;
    10411059        int src2 = (++vPC)->u.operand;
    1042         r[dst].u.jsValue = jsNumber(r[src1].u.jsValue->toNumber(exec) * r[src2].u.jsValue->toNumber(exec));
    1043        
     1060        JSValue* result = jsNumber(r[src1].u.jsValue->toNumber(exec) * r[src2].u.jsValue->toNumber(exec));
     1061        VM_CHECK_EXCEPTION();
     1062        r[dst].u.jsValue = result;
     1063
    10441064        ++vPC;
    10451065        NEXT_OPCODE;
     
    10551075        int dividend = (++vPC)->u.operand;
    10561076        int divisor = (++vPC)->u.operand;
    1057         r[dst].u.jsValue = jsNumber(r[dividend].u.jsValue->toNumber(exec) / r[divisor].u.jsValue->toNumber(exec));
    1058        
     1077        JSValue* result = jsNumber(r[dividend].u.jsValue->toNumber(exec) / r[divisor].u.jsValue->toNumber(exec));
     1078        VM_CHECK_EXCEPTION();
     1079        r[dst].u.jsValue = result;
    10591080        ++vPC;
    10601081        NEXT_OPCODE;
     
    10701091        int dividend = (++vPC)->u.operand;
    10711092        int divisor = (++vPC)->u.operand;
    1072         Instruction* firstTarget;
    1073         Instruction* secondTarget;
    1074         double left = r[dividend].u.jsValue->toNumber(exec, vPC, builtinThrowBuffer, firstTarget);
    1075         double right = r[divisor].u.jsValue->toNumber(exec, firstTarget, builtinThrowBuffer, secondTarget);
    1076         r[dst].u.jsValue = jsNumber(fmod(left, right));
    1077        
    1078         vPC = secondTarget + 1;
     1093        double d = r[dividend].u.jsValue->toNumber(exec);
     1094        JSValue* result = jsNumber(fmod(d, r[divisor].u.jsValue->toNumber(exec)));
     1095        VM_CHECK_EXCEPTION();
     1096        r[dst].u.jsValue = result;
     1097        ++vPC;
    10791098        NEXT_OPCODE;
    10801099    }
     
    10891108        int src1 = (++vPC)->u.operand;
    10901109        int src2 = (++vPC)->u.operand;
    1091         Instruction* firstTarget;
    1092         Instruction* secondTarget;
    1093         double left = r[src1].u.jsValue->toNumber(exec, vPC, builtinThrowBuffer, firstTarget);
    1094         double right = r[src2].u.jsValue->toNumber(exec, firstTarget, builtinThrowBuffer, secondTarget);
    1095         r[dst].u.jsValue = jsNumber(left - right);
    1096        
    1097         vPC = secondTarget + 1;
     1110        JSValue* result = jsNumber(r[src1].u.jsValue->toNumber(exec) - r[src2].u.jsValue->toNumber(exec));
     1111        VM_CHECK_EXCEPTION();
     1112        r[dst].u.jsValue = result;
     1113        ++vPC;
    10981114        NEXT_OPCODE;
    10991115    }
     
    11081124        int val = (++vPC)->u.operand;
    11091125        int shift = (++vPC)->u.operand;
    1110         r[dst].u.jsValue = jsNumber((r[val].u.jsValue->toInt32(exec)) << (r[shift].u.jsValue->toUInt32(exec)));
     1126        JSValue* result = jsNumber((r[val].u.jsValue->toInt32(exec)) << (r[shift].u.jsValue->toUInt32(exec)));
     1127        VM_CHECK_EXCEPTION();
     1128        r[dst].u.jsValue = result;
    11111129       
    11121130        ++vPC;
     
    11231141        int val = (++vPC)->u.operand;
    11241142        int shift = (++vPC)->u.operand;
    1125         r[dst].u.jsValue = jsNumber((r[val].u.jsValue->toInt32(exec)) >> (r[shift].u.jsValue->toUInt32(exec)));
     1143        JSValue* result = jsNumber((r[val].u.jsValue->toInt32(exec)) >> (r[shift].u.jsValue->toUInt32(exec)));
     1144        VM_CHECK_EXCEPTION();
     1145        r[dst].u.jsValue = result;
    11261146       
    11271147        ++vPC;
     
    11381158        int val = (++vPC)->u.operand;
    11391159        int shift = (++vPC)->u.operand;
    1140         r[dst].u.jsValue = jsNumber((r[val].u.jsValue->toUInt32(exec)) >> (r[shift].u.jsValue->toUInt32(exec)));
     1160        JSValue* result = jsNumber((r[val].u.jsValue->toUInt32(exec)) >> (r[shift].u.jsValue->toUInt32(exec)));
     1161        VM_CHECK_EXCEPTION();
     1162        r[dst].u.jsValue = result;
    11411163       
    11421164        ++vPC;
     
    11531175        int src1 = (++vPC)->u.operand;
    11541176        int src2 = (++vPC)->u.operand;
    1155         r[dst].u.jsValue = jsNumber((r[src1].u.jsValue->toInt32(exec)) & (r[src2].u.jsValue->toInt32(exec)));
     1177        JSValue* result = jsNumber((r[src1].u.jsValue->toInt32(exec)) & (r[src2].u.jsValue->toInt32(exec)));
     1178        VM_CHECK_EXCEPTION();
     1179        r[dst].u.jsValue = result;
    11561180       
    11571181        ++vPC;
     
    11681192        int src1 = (++vPC)->u.operand;
    11691193        int src2 = (++vPC)->u.operand;
    1170         r[dst].u.jsValue = jsNumber((r[src1].u.jsValue->toInt32(exec)) ^ (r[src2].u.jsValue->toInt32(exec)));
     1194        JSValue* result = jsNumber((r[src1].u.jsValue->toInt32(exec)) ^ (r[src2].u.jsValue->toInt32(exec)));
     1195        VM_CHECK_EXCEPTION();
     1196        r[dst].u.jsValue = result;
    11711197       
    11721198        ++vPC;
     
    11831209        int src1 = (++vPC)->u.operand;
    11841210        int src2 = (++vPC)->u.operand;
    1185         r[dst].u.jsValue = jsNumber((r[src1].u.jsValue->toInt32(exec)) | (r[src2].u.jsValue->toInt32(exec)));
     1211        JSValue* result = jsNumber((r[src1].u.jsValue->toInt32(exec)) | (r[src2].u.jsValue->toInt32(exec)));
     1212        VM_CHECK_EXCEPTION();
     1213        r[dst].u.jsValue = result;
    11861214       
    11871215        ++vPC;
     
    11961224        int dst = (++vPC)->u.operand;
    11971225        int src = (++vPC)->u.operand;
    1198         r[dst].u.jsValue = jsNumber(~r[src].u.jsValue->toInt32(exec));
     1226        JSValue* result = jsNumber(~r[src].u.jsValue->toInt32(exec));
     1227        VM_CHECK_EXCEPTION();
     1228        r[dst].u.jsValue = result;
    11991229
    12001230        ++vPC;
     
    12091239        int dst = (++vPC)->u.operand;
    12101240        int src = (++vPC)->u.operand;
    1211         r[dst].u.jsValue = jsBoolean(!r[src].u.jsValue->toBoolean(exec));
     1241        JSValue* result = jsBoolean(!r[src].u.jsValue->toBoolean(exec));
     1242        VM_CHECK_EXCEPTION();
     1243        r[dst].u.jsValue = result;
    12121244
    12131245        ++vPC;
     
    20182050        NEXT_OPCODE;
    20192051    }
    2020     BEGIN_OPCODE(op_builtin_throw) {
    2021         ASSERT(exec->exceptionSource()->u.opcode != getOpcode(op_builtin_throw));
    2022         exceptionValue = exec->exception();
    2023         vPC = exec->exceptionSource();
    2024         exec->clearExceptionSource();
    2025         exec->clearException();
    2026         // fall through to vm_throw to allow shared logic to do the actual
    2027         // exception handling.
    2028     }
    20292052    vm_throw: {
    20302053        exec->clearException();
  • branches/squirrelfish/JavaScriptCore/VM/Opcode.h

    r33335 r33393  
    109109        macro(op_catch) \
    110110        macro(op_throw) \
    111         macro(op_builtin_throw) \
    112111        macro(op_new_error) \
    113112        \
  • branches/squirrelfish/JavaScriptCore/kjs/value.h

    r33233 r33393  
    7373    bool getNumber(double&) const;
    7474    double getNumber() const; // NaN if not a number
     75    double uncheckedGetNumber() const;
    7576    bool getString(UString&) const;
    7677    UString getString() const; // null string if not a string
     
    9192
    9293    bool toBoolean(ExecState *exec) const;
     94
     95    // toNumber conversion is expected to be side effect free if an exception has
     96    // been set in the ExecState already.
    9397    double toNumber(ExecState *exec) const;
    9498    double toNumber(ExecState* exec, Instruction* normalExitPC, Instruction* exceptionExitPC, Instruction*& resultPC) const;
     
    416420}
    417421
     422inline double JSValue::uncheckedGetNumber() const
     423{
     424    ASSERT(JSImmediate::isImmediate(this) || asCell()->isNumber());
     425    return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : static_cast<const NumberImp*>(this)->value();
     426}
     427
    418428inline bool JSValue::getString(UString& s) const
    419429{
  • branches/squirrelfish/LayoutTests/ChangeLog

    r33383 r33393  
     12008-05-13  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Darin.
     4
     5        Bug 18752: SQUIRRELFISH: exceptions are not always handled by the vm
     6        <https://bugs.webkit.org/show_bug.cgi?id=18752>
     7
     8        Fairly extensive coverage of exception behaviour and sequencing.  There
     9        are still a number of FAIL results but these all match firefox (although
     10        not opera).
     11
     12        * fast/js/exception-sequencing-expected.txt: Added.
     13        * fast/js/exception-sequencing.html: Added.
     14
    1152008-05-13  Maciej Stachowiak  <mjs@apple.com>
    216
Note: See TracChangeset for help on using the changeset viewer.