Changeset 33393 in webkit
- Timestamp:
- May 13, 2008 2:50:55 PM (16 years ago)
- Location:
- branches/squirrelfish
- Files:
-
- 2 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/squirrelfish/JavaScriptCore/ChangeLog
r33386 r33393 1 2008-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 1 27 2008-05-13 Geoffrey Garen <ggaren@apple.com> 2 28 -
branches/squirrelfish/JavaScriptCore/VM/Machine.cpp
r33386 r33393 157 157 158 158 if (bothTypes == ((NumberType << 3) | NumberType)) 159 return jsNumber(v1-> toNumber(exec) + v2->toNumber(exec));159 return jsNumber(v1->uncheckedGetNumber() + v2->uncheckedGetNumber()); 160 160 if (bothTypes == ((StringType << 3) | StringType)) { 161 161 UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value(); … … 210 210 JSObject* o = *iter; 211 211 if (o->getPropertySlot(exec, ident, slot)) { 212 r[dst].u.jsValue= slot.getValue(exec, o, ident);212 JSValue* result = slot.getValue(exec, o, ident); 213 213 exceptionValue = exec->exception(); 214 return !exceptionValue; 214 if (exceptionValue) 215 return false; 216 r[dst].u.jsValue = result; 217 return true; 215 218 } 216 219 } while (++iter != end); … … 260 263 do { 261 264 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; 263 271 r[baseDst].u.jsValue = base; 264 r[propDst].u.jsValue = slot.getValue(exec, base, ident);265 272 return true; 266 273 } … … 299 306 // We also handle wrapper substitution for the global object at the same time. 300 307 JSObject* thisObj = base->toThisObject(exec); 308 JSValue* result = slot.getValue(exec, base, ident); 309 exceptionValue = exec->exception(); 310 if (exceptionValue) 311 return false; 301 312 302 313 r[baseDst].u.jsValue = thisObj; 303 r[funcDst].u.jsValue = slot.getValue(exec, base, ident);314 r[funcDst].u.jsValue = result; 304 315 return true; 305 316 } … … 738 749 return 0; 739 750 } 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 747 752 JSValue* exceptionValue = 0; 748 753 Instruction* handlerVPC = 0; … … 909 914 int src1 = (++vPC)->u.operand; 910 915 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; 912 919 913 920 ++vPC; … … 924 931 int src1 = (++vPC)->u.operand; 925 932 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; 927 936 928 937 ++vPC; … … 936 945 */ 937 946 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; 943 952 NEXT_OPCODE; 944 953 } … … 950 959 */ 951 960 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; 957 966 NEXT_OPCODE; 958 967 } … … 966 975 int dst = (++vPC)->u.operand; 967 976 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); 970 982 971 983 ++vPC; … … 981 993 int dst = (++vPC)->u.operand; 982 994 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); 985 1000 986 1001 ++vPC; … … 995 1010 int dst = (++vPC)->u.operand; 996 1011 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; 998 1016 999 1017 ++vPC; … … 1008 1026 int dst = (++vPC)->u.operand; 1009 1027 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; 1016 1033 NEXT_OPCODE; 1017 1034 } … … 1026 1043 int src1 = (++vPC)->u.operand; 1027 1044 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; 1030 1048 ++vPC; 1031 1049 NEXT_OPCODE; … … 1040 1058 int src1 = (++vPC)->u.operand; 1041 1059 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 1044 1064 ++vPC; 1045 1065 NEXT_OPCODE; … … 1055 1075 int dividend = (++vPC)->u.operand; 1056 1076 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; 1059 1080 ++vPC; 1060 1081 NEXT_OPCODE; … … 1070 1091 int dividend = (++vPC)->u.operand; 1071 1092 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; 1079 1098 NEXT_OPCODE; 1080 1099 } … … 1089 1108 int src1 = (++vPC)->u.operand; 1090 1109 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; 1098 1114 NEXT_OPCODE; 1099 1115 } … … 1108 1124 int val = (++vPC)->u.operand; 1109 1125 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; 1111 1129 1112 1130 ++vPC; … … 1123 1141 int val = (++vPC)->u.operand; 1124 1142 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; 1126 1146 1127 1147 ++vPC; … … 1138 1158 int val = (++vPC)->u.operand; 1139 1159 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; 1141 1163 1142 1164 ++vPC; … … 1153 1175 int src1 = (++vPC)->u.operand; 1154 1176 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; 1156 1180 1157 1181 ++vPC; … … 1168 1192 int src1 = (++vPC)->u.operand; 1169 1193 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; 1171 1197 1172 1198 ++vPC; … … 1183 1209 int src1 = (++vPC)->u.operand; 1184 1210 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; 1186 1214 1187 1215 ++vPC; … … 1196 1224 int dst = (++vPC)->u.operand; 1197 1225 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; 1199 1229 1200 1230 ++vPC; … … 1209 1239 int dst = (++vPC)->u.operand; 1210 1240 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; 1212 1244 1213 1245 ++vPC; … … 2018 2050 NEXT_OPCODE; 2019 2051 } 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 actual2027 // exception handling.2028 }2029 2052 vm_throw: { 2030 2053 exec->clearException(); -
branches/squirrelfish/JavaScriptCore/VM/Opcode.h
r33335 r33393 109 109 macro(op_catch) \ 110 110 macro(op_throw) \ 111 macro(op_builtin_throw) \112 111 macro(op_new_error) \ 113 112 \ -
branches/squirrelfish/JavaScriptCore/kjs/value.h
r33233 r33393 73 73 bool getNumber(double&) const; 74 74 double getNumber() const; // NaN if not a number 75 double uncheckedGetNumber() const; 75 76 bool getString(UString&) const; 76 77 UString getString() const; // null string if not a string … … 91 92 92 93 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. 93 97 double toNumber(ExecState *exec) const; 94 98 double toNumber(ExecState* exec, Instruction* normalExitPC, Instruction* exceptionExitPC, Instruction*& resultPC) const; … … 416 420 } 417 421 422 inline 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 418 428 inline bool JSValue::getString(UString& s) const 419 429 { -
branches/squirrelfish/LayoutTests/ChangeLog
r33383 r33393 1 2008-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 1 15 2008-05-13 Maciej Stachowiak <mjs@apple.com> 2 16
Note: See TracChangeset
for help on using the changeset viewer.