Changeset 41100 in webkit for trunk/JavaScriptCore/runtime
- Timestamp:
- Feb 19, 2009, 10:04:21 PM (16 years ago)
- Location:
- trunk/JavaScriptCore/runtime
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/Operations.cpp
r39851 r41100 53 53 } 54 54 55 NEVER_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 71 JSValuePtr 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 93 bool 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 111 bool 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 55 121 } // namespace JSC -
trunk/JavaScriptCore/runtime/Operations.h
r40046 r41100 23 23 #define Operations_h 24 24 25 #include "Interpreter.h" 25 26 #include "JSImmediate.h" 26 27 #include "JSNumberCell.h" … … 28 29 29 30 namespace 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); 30 37 31 38 // ECMA 11.9.3 … … 130 137 } 131 138 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.