Changeset 36016 in webkit for trunk/JavaScriptCore/VM/Machine.cpp
- Timestamp:
- Sep 1, 2008, 2:22:54 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/VM/Machine.cpp
r36006 r36016 475 475 { 476 476 if (newCodeBlock->needsFullScopeChain) { 477 JSActivation* activation = new (exec) JSActivation( functionBodyNode, r);477 JSActivation* activation = new (exec) JSActivation(exec, functionBodyNode, r); 478 478 r[RegisterFile::OptionalCalleeActivation - RegisterFile::CallFrameHeaderSize - newCodeBlock->numLocals] = activation; 479 479 … … 540 540 void* storage = fastMalloc(sizeof(CollectorBlock)); 541 541 542 JSArray* jsArray = new (storage) JSArray( jsNull(), 0);542 JSArray* jsArray = new (storage) JSArray(JSArray::DummyConstruct); 543 543 m_jsArrayVptr = jsArray->vptr(); 544 544 static_cast<JSCell*>(jsArray)->~JSCell(); … … 626 626 #endif 627 627 628 #if !defined(NDEBUG) || HAVE(SAMPLING_TOOL)628 #if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL) 629 629 630 630 bool Machine::isOpcode(Opcode opcode) … … 889 889 for (Node::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) { 890 890 const Identifier& ident = (*it).first; 891 if (!variableObject->hasProperty(exec, ident)) 892 variableObject->put(exec, ident, jsUndefined()); 891 if (!variableObject->hasProperty(exec, ident)) { 892 PutPropertySlot slot; 893 variableObject->put(exec, ident, jsUndefined(), slot); 894 } 893 895 } 894 896 895 897 const Node::FunctionStack& functionStack = codeBlock->ownerNode->functionStack(); 896 898 Node::FunctionStack::const_iterator functionStackEnd = functionStack.end(); 897 for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) 898 variableObject->put(exec, (*it)->m_ident, (*it)->makeFunction(exec, scopeChain)); 899 for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) { 900 PutPropertySlot slot; 901 variableObject->put(exec, (*it)->m_ident, (*it)->makeFunction(exec, scopeChain), slot); 902 } 899 903 900 904 size_t oldSize = m_registerFile.size(); … … 1086 1090 Identifier& property = codeBlock->identifiers[(++vPC)->u.operand]; 1087 1091 JSValue* value = r[(++vPC)->u.operand].jsValue(exec); 1088 JSObject* scope = new (exec) JSStaticScopeObject( property, value, DontDelete);1092 JSObject* scope = new (exec) JSStaticScopeObject(exec, property, value, DontDelete); 1089 1093 r[dst] = scope; 1090 1094 return scopeChain->push(scope); 1095 } 1096 1097 StructureIDChain* cachePrototypeChain(StructureID* structureID) 1098 { 1099 RefPtr<StructureIDChain> chain = StructureIDChain::create(static_cast<JSCell*>(structureID->prototype())->structureID()); 1100 structureID->setCachedPrototypeChain(chain.release()); 1101 return structureID->cachedPrototypeChain(); 1102 } 1103 1104 NEVER_INLINE void Machine::tryCachePutByID(CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const PutPropertySlot& slot) 1105 { 1106 // Recursive invocation may already have specialized this instruction. 1107 if (vPC[0].u.opcode != getOpcode(op_put_by_id)) 1108 return; 1109 1110 if (JSImmediate::isImmediate(baseValue)) 1111 return; 1112 1113 // Uncacheable: give up. 1114 if (!slot.isCacheable()) { 1115 vPC[0] = getOpcode(op_put_by_id_generic); 1116 return; 1117 } 1118 1119 // FIXME: Cache new property transitions, too. 1120 if (slot.type() == PutPropertySlot::NewProperty) { 1121 vPC[0] = getOpcode(op_put_by_id_generic); 1122 return; 1123 } 1124 1125 JSCell* baseCell = static_cast<JSCell*>(baseValue); 1126 StructureID* structureID = baseCell->structureID(); 1127 1128 // FIXME: Remove this !structureID check once all objects have StructureIDs. 1129 if (!structureID) { 1130 vPC[0] = getOpcode(op_put_by_id_generic); 1131 return; 1132 } 1133 1134 if (structureID->isDictionary()) { 1135 vPC[0] = getOpcode(op_put_by_id_generic); 1136 return; 1137 } 1138 1139 // Cache miss: record StructureID to compare against next time. 1140 StructureID* lastStructureID = vPC[4].u.structureID; 1141 if (structureID != lastStructureID) { 1142 // First miss: record StructureID to compare against next time. 1143 if (!lastStructureID) { 1144 vPC[4] = structureID; 1145 return; 1146 } 1147 1148 // Second miss: give up. 1149 vPC[0] = getOpcode(op_put_by_id_generic); 1150 return; 1151 } 1152 1153 // Cache hit: Specialize instruction and ref StructureIDs. 1154 1155 // If baseCell != slotBase, then baseCell must be a proxy for another object. 1156 if (baseCell != slot.slotBase()) { 1157 vPC[0] = getOpcode(op_put_by_id_generic); 1158 return; 1159 } 1160 vPC[0] = getOpcode(op_put_by_id_replace); 1161 vPC[5] = slot.cachedOffset(); 1162 codeBlock->refStructureIDs(vPC); 1163 } 1164 1165 NEVER_INLINE void Machine::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC) 1166 { 1167 codeBlock->derefStructureIDs(vPC); 1168 vPC[0] = getOpcode(op_put_by_id); 1169 vPC[4] = 0; 1170 } 1171 1172 NEVER_INLINE void Machine::tryCacheGetByID(CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const PropertySlot& slot) 1173 { 1174 // Recursive invocation may already have specialized this instruction. 1175 if (vPC[0].u.opcode != getOpcode(op_get_by_id)) 1176 return; 1177 1178 // Uncacheable: give up. 1179 if (!slot.isCacheable()) { 1180 vPC[0] = getOpcode(op_get_by_id_generic); 1181 return; 1182 } 1183 1184 // FIXME: Cache property access for immediates. 1185 if (JSImmediate::isImmediate(baseValue)) { 1186 vPC[0] = getOpcode(op_get_by_id_generic); 1187 return; 1188 } 1189 1190 JSCell* baseCell = static_cast<JSCell*>(baseValue); 1191 StructureID* structureID = baseCell->structureID(); 1192 1193 // FIXME: Remove this !structureID check once all JSCells have StructureIDs. 1194 if (!structureID) { 1195 vPC[0] = getOpcode(op_get_by_id_generic); 1196 return; 1197 } 1198 1199 if (structureID->isDictionary()) { 1200 vPC[0] = getOpcode(op_get_by_id_generic); 1201 return; 1202 } 1203 1204 // Cache miss 1205 StructureID* lastStructureID = vPC[4].u.structureID; 1206 if (structureID != lastStructureID) { 1207 // First miss: record StructureID to compare against next time. 1208 if (!lastStructureID) { 1209 vPC[4] = structureID; 1210 return; 1211 } 1212 1213 // Second miss: give up. 1214 vPC[0] = getOpcode(op_get_by_id_generic); 1215 return; 1216 } 1217 1218 // Cache hit: Specialize instruction and ref StructureIDs. 1219 1220 JSValue* slotBase = slot.slotBase(); 1221 if (slotBase == baseCell) { 1222 vPC[0] = getOpcode(op_get_by_id_self); 1223 vPC[5] = slot.cachedOffset(); 1224 1225 codeBlock->refStructureIDs(vPC); 1226 return; 1227 } 1228 1229 if (slotBase == structureID->prototype()) { 1230 ASSERT(!JSImmediate::isImmediate(slotBase)); 1231 1232 vPC[0] = getOpcode(op_get_by_id_proto); 1233 vPC[5] = static_cast<JSCell*>(slotBase)->structureID(); 1234 vPC[6] = slot.cachedOffset(); 1235 1236 codeBlock->refStructureIDs(vPC); 1237 return; 1238 } 1239 1240 size_t count = 0; 1241 while (baseCell != slotBase) { 1242 baseCell = static_cast<JSCell*>(baseCell->structureID()->prototype()); 1243 // If we didn't find slotBase in baseCell's prototype chain, then baseCell 1244 // must be a proxy for another object. 1245 if (baseCell == jsNull()) { 1246 vPC[0] = getOpcode(op_get_by_id_generic); 1247 return; 1248 } 1249 ++count; 1250 } 1251 1252 StructureIDChain* chain = structureID->cachedPrototypeChain(); 1253 if (!chain) 1254 chain = cachePrototypeChain(structureID); 1255 1256 vPC[0] = getOpcode(op_get_by_id_chain); 1257 vPC[4] = structureID; 1258 vPC[5] = chain; 1259 vPC[6] = count; 1260 vPC[7] = slot.cachedOffset(); 1261 codeBlock->refStructureIDs(vPC); 1262 } 1263 1264 NEVER_INLINE void Machine::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC) 1265 { 1266 codeBlock->derefStructureIDs(vPC); 1267 vPC[0] = getOpcode(op_get_by_id); 1268 vPC[4] = 0; 1091 1269 } 1092 1270 … … 1244 1422 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec); 1245 1423 if (JSImmediate::areBothImmediateNumbers(src1, src2)) 1246 r[dst] = jsBoolean( reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));1424 r[dst] = jsBoolean(src1 != src2); 1247 1425 else { 1248 1426 JSValue* result = jsBoolean(!equal(exec, src1, src2)); … … 1935 2113 } 1936 2114 BEGIN_OPCODE(op_get_by_id) { 1937 /* get_by_id dst(r) base(r) property(id) 1938 1939 Converts register base to Object, gets the property 1940 named by identifier property from the object, and puts the 1941 result in register dst. 1942 */ 1943 int dst = (++vPC)->u.operand; 1944 int base = (++vPC)->u.operand; 1945 int property = (++vPC)->u.operand; 2115 /* get_by_id dst(r) base(r) property(id) structureID(sID) nop(n) nop(n) nop(n) 2116 2117 Generic property access: Gets the property named by identifier 2118 property from the value base, and puts the result in register dst. 2119 */ 2120 int dst = vPC[1].u.operand; 2121 int base = vPC[2].u.operand; 2122 int property = vPC[3].u.operand; 1946 2123 1947 2124 Identifier& ident = codeBlock->identifiers[property]; 1948 JSValue* result = r[base].jsValue(exec)->get(exec, ident); 2125 JSValue* baseValue = r[base].jsValue(exec); 2126 PropertySlot slot(baseValue); 2127 JSValue* result = baseValue->get(exec, ident, slot); 1949 2128 VM_CHECK_EXCEPTION(); 2129 2130 tryCacheGetByID(codeBlock, vPC, baseValue, slot); 2131 1950 2132 r[dst] = result; 1951 ++vPC; 2133 vPC += 8; 2134 NEXT_OPCODE; 2135 } 2136 BEGIN_OPCODE(op_get_by_id_self) { 2137 /* op_get_by_id_self dst(r) base(r) property(id) structureID(sID) offset(n) nop(n) nop(n) 2138 2139 Cached property access: Attempts to get a cached property from the 2140 value base. If the cache misses, op_get_by_id_self reverts to 2141 op_get_by_id. 2142 */ 2143 int base = vPC[2].u.operand; 2144 JSValue* baseValue = r[base].jsValue(exec); 2145 2146 if (LIKELY(!JSImmediate::isImmediate(baseValue))) { 2147 JSCell* baseCell = static_cast<JSCell*>(baseValue); 2148 StructureID* structureID = vPC[4].u.structureID; 2149 2150 if (LIKELY(baseCell->structureID() == structureID)) { 2151 ASSERT(baseCell->isObject()); 2152 JSObject* baseObject = static_cast<JSObject*>(baseCell); 2153 int dst = vPC[1].u.operand; 2154 int offset = vPC[5].u.operand; 2155 2156 ASSERT(baseObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset)); 2157 r[dst] = baseObject->getDirectOffset(offset); 2158 2159 vPC += 8; 2160 NEXT_OPCODE; 2161 } 2162 } 2163 2164 uncacheGetByID(codeBlock, vPC); 2165 NEXT_OPCODE; 2166 } 2167 BEGIN_OPCODE(op_get_by_id_proto) { 2168 /* op_get_by_id_proto dst(r) base(r) property(id) structureID(sID) protoStructureID(sID) offset(n) nop(n) 2169 2170 Cached property access: Attempts to get a cached property from the 2171 value base's prototype. If the cache misses, op_get_by_id_proto 2172 reverts to op_get_by_id. 2173 */ 2174 int base = vPC[2].u.operand; 2175 JSValue* baseValue = r[base].jsValue(exec); 2176 2177 if (LIKELY(!JSImmediate::isImmediate(baseValue))) { 2178 JSCell* baseCell = static_cast<JSCell*>(baseValue); 2179 StructureID* structureID = vPC[4].u.structureID; 2180 2181 if (LIKELY(baseCell->structureID() == structureID)) { 2182 ASSERT(structureID->prototype()->isObject()); 2183 JSObject* protoObject = static_cast<JSObject*>(structureID->prototype()); 2184 StructureID* protoStructureID = vPC[5].u.structureID; 2185 2186 if (LIKELY(protoObject->structureID() == protoStructureID)) { 2187 int dst = vPC[1].u.operand; 2188 int offset = vPC[6].u.operand; 2189 2190 ASSERT(protoObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == protoObject->getDirectOffset(offset)); 2191 r[dst] = protoObject->getDirectOffset(offset); 2192 2193 vPC += 8; 2194 NEXT_OPCODE; 2195 } 2196 } 2197 } 2198 2199 uncacheGetByID(codeBlock, vPC); 2200 NEXT_OPCODE; 2201 } 2202 BEGIN_OPCODE(op_get_by_id_chain) { 2203 /* op_get_by_id_chain dst(r) base(r) property(id) structureID(sID) structureIDChain(sIDc) count(n) offset(n) 2204 2205 Cached property access: Attempts to get a cached property from the 2206 value base's prototype chain. If the cache misses, op_get_by_id_proto 2207 reverts to op_get_by_id. 2208 */ 2209 int base = vPC[2].u.operand; 2210 JSValue* baseValue = r[base].jsValue(exec); 2211 2212 if (LIKELY(!JSImmediate::isImmediate(baseValue))) { 2213 JSCell* baseCell = static_cast<JSCell*>(baseValue); 2214 StructureID* structureID = vPC[4].u.structureID; 2215 2216 if (LIKELY(baseCell->structureID() == structureID)) { 2217 RefPtr<StructureID>* it = vPC[5].u.structureIDChain->head(); 2218 size_t count = vPC[6].u.operand; 2219 RefPtr<StructureID>* end = it + count; 2220 2221 while (1) { 2222 baseCell = static_cast<JSCell*>(baseCell->structureID()->prototype()); 2223 if (UNLIKELY(baseCell->structureID() != (*it).get())) 2224 break; 2225 2226 if (++it == end) { 2227 ASSERT(baseCell->isObject()); 2228 JSObject* baseObject = static_cast<JSObject*>(baseCell); 2229 int dst = vPC[1].u.operand; 2230 int offset = vPC[7].u.operand; 2231 2232 ASSERT(baseObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset)); 2233 r[dst] = baseObject->getDirectOffset(offset); 2234 2235 vPC += 8; 2236 NEXT_OPCODE; 2237 } 2238 } 2239 } 2240 } 2241 2242 uncacheGetByID(codeBlock, vPC); 2243 NEXT_OPCODE; 2244 } 2245 BEGIN_OPCODE(op_get_by_id_generic) { 2246 /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) 2247 2248 Generic property access: Gets the property named by identifier 2249 property from the value base, and puts the result in register dst. 2250 */ 2251 int dst = vPC[1].u.operand; 2252 int base = vPC[2].u.operand; 2253 int property = vPC[3].u.operand; 2254 2255 Identifier& ident = codeBlock->identifiers[property]; 2256 JSValue* baseValue = r[base].jsValue(exec); 2257 PropertySlot slot(baseValue); 2258 JSValue* result = baseValue->get(exec, ident, slot); 2259 VM_CHECK_EXCEPTION(); 2260 2261 r[dst] = result; 2262 vPC += 8; 1952 2263 NEXT_OPCODE; 1953 2264 } 1954 2265 BEGIN_OPCODE(op_put_by_id) { 1955 /* put_by_id base(r) property(id) value(r) 2266 /* put_by_id base(r) property(id) value(r) nop(n) nop(n) 1956 2267 1957 2268 Sets register value on register base as the property named … … 1961 2272 the register file. 1962 2273 */ 1963 int base = (++vPC)->u.operand; 1964 int property = (++vPC)->u.operand; 1965 int value = (++vPC)->u.operand; 1966 2274 2275 int base = vPC[1].u.operand; 2276 int property = vPC[2].u.operand; 2277 int value = vPC[3].u.operand; 2278 2279 JSValue* baseValue = r[base].jsValue(exec); 2280 2281 PutPropertySlot slot; 1967 2282 Identifier& ident = codeBlock->identifiers[property]; 1968 r[base].jsValue(exec)->put(exec, ident, r[value].jsValue(exec)); 1969 2283 baseValue->put(exec, ident, r[value].jsValue(exec), slot); 1970 2284 VM_CHECK_EXCEPTION(); 1971 ++vPC; 2285 2286 tryCachePutByID(codeBlock, vPC, baseValue, slot); 2287 2288 vPC += 6; 2289 NEXT_OPCODE; 2290 } 2291 BEGIN_OPCODE(op_put_by_id_replace) { 2292 /* op_put_by_id_replace base(r) property(id) value(r) structureID(sID) offset(n) 2293 2294 Sets register value on register base as the property named 2295 by identifier property. Base is converted to object first. 2296 2297 Unlike many opcodes, this one does not write any output to 2298 the register file. 2299 */ 2300 int base = vPC[1].u.operand; 2301 JSValue* baseValue = r[base].jsValue(exec); 2302 2303 if (LIKELY(!JSImmediate::isImmediate(baseValue))) { 2304 JSCell* baseCell = static_cast<JSCell*>(baseValue); 2305 StructureID* structureID = vPC[4].u.structureID; 2306 2307 if (LIKELY(baseCell->structureID() == structureID)) { 2308 ASSERT(baseCell->isObject()); 2309 JSObject* baseObject = static_cast<JSObject*>(baseCell); 2310 int value = vPC[3].u.operand; 2311 unsigned offset = vPC[5].u.operand; 2312 2313 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(codeBlock->identifiers[vPC[2].u.operand])) == offset); 2314 baseObject->putDirectOffset(offset, r[value].jsValue(exec)); 2315 2316 vPC += 6; 2317 NEXT_OPCODE; 2318 } 2319 } 2320 2321 uncachePutByID(codeBlock, vPC); 2322 NEXT_OPCODE; 2323 } 2324 BEGIN_OPCODE(op_put_by_id_generic) { 2325 /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) 2326 2327 Sets register value on register base as the property named 2328 by identifier property. Base is converted to object first. 2329 2330 Unlike many opcodes, this one does not write any output to 2331 the register file. 2332 */ 2333 int base = vPC[1].u.operand; 2334 int property = vPC[2].u.operand; 2335 int value = vPC[3].u.operand; 2336 2337 JSValue* baseValue = r[base].jsValue(exec); 2338 2339 PutPropertySlot slot; 2340 Identifier& ident = codeBlock->identifiers[property]; 2341 baseValue->put(exec, ident, r[value].jsValue(exec), slot); 2342 VM_CHECK_EXCEPTION(); 2343 2344 vPC += 6; 1972 2345 NEXT_OPCODE; 1973 2346 } … … 2065 2438 } else { 2066 2439 Identifier property(exec, subscript->toString(exec)); 2067 if (!exec->hadException()) // Don't put to an object if toString threw an exception. 2068 baseValue->put(exec, property, r[value].jsValue(exec)); 2440 if (!exec->hadException()) { // Don't put to an object if toString threw an exception. 2441 PutPropertySlot slot; 2442 baseValue->put(exec, property, r[value].jsValue(exec), slot); 2443 } 2069 2444 } 2070 2445 … … 2934 3309 if (!activation) { 2935 3310 CodeBlock* codeBlock = &function->m_body->generatedByteCode(); 2936 activation = new (exec) JSActivation( function->m_body, callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numLocals);3311 activation = new (exec) JSActivation(exec, function->m_body, callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numLocals); 2937 3312 callFrame[RegisterFile::OptionalCalleeActivation] = activation; 2938 3313 }
Note:
See TracChangeset
for help on using the changeset viewer.