Changeset 153221 in webkit for trunk/Source/JavaScriptCore/runtime/JSScope.cpp
- Timestamp:
- Jul 24, 2013, 9:02:40 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/runtime/JSScope.cpp
r153170 r153221 48 48 } 49 49 50 bool JSScope::isDynamicScope(bool& requiresDynamicChecks) const 50 // Returns true if we found enough information to terminate optimization. 51 static inline bool abstractAccess(ExecState* exec, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, size_t depth, bool& needsVarInjectionChecks, ResolveOp& op) 51 52 { 52 switch (structure()->typeInfo().type()) { 53 case GlobalObjectType: 54 return static_cast<const JSGlobalObject*>(this)->isDynamicScope(requiresDynamicChecks); 55 case ActivationObjectType: 56 return static_cast<const JSActivation*>(this)->isDynamicScope(requiresDynamicChecks); 57 case NameScopeObjectType: 58 return static_cast<const JSNameScope*>(this)->isDynamicScope(requiresDynamicChecks); 59 default: 60 RELEASE_ASSERT_NOT_REACHED(); 61 break; 53 if (JSActivation* activation = jsDynamicCast<JSActivation*>(scope)) { 54 if (ident == exec->propertyNames().arguments) { 55 // We know the property will be at this activation scope, but we don't know how to cache it. 56 op = ResolveOp(Dynamic, 0, 0, 0); 57 return true; 58 } 59 60 SymbolTableEntry entry = activation->symbolTable()->get(ident.impl()); 61 if (entry.isReadOnly() && getOrPut == Put) { 62 // We know the property will be at this activation scope, but we don't know how to cache it. 63 op = ResolveOp(Dynamic, 0, 0, 0); 64 return true; 65 } 66 67 if (!entry.isNull()) { 68 op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, activation->structure(), entry.getIndex()); 69 return true; 70 } 71 72 if (activation->symbolTable()->usesNonStrictEval()) 73 needsVarInjectionChecks = true; 74 return false; 62 75 } 63 76 64 return false; 77 if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(scope)) { 78 SymbolTableEntry entry = globalObject->symbolTable()->get(ident.impl()); 79 if (!entry.isNull()) { 80 if (getOrPut == Put) { 81 if (entry.isReadOnly()) { 82 // We know the property will be at global scope, but we don't know how to cache it. 83 op = ResolveOp(Dynamic, 0, 0, 0); 84 return true; 85 } 86 87 // It's likely that we'll write to this var, so notify now and avoid the overhead of doing so at runtime. 88 entry.notifyWrite(); 89 } 90 91 op = ResolveOp(makeType(GlobalVar, needsVarInjectionChecks), depth, globalObject->structure(), 92 reinterpret_cast<uintptr_t>(globalObject->registerAt(entry.getIndex()).slot())); 93 return true; 94 } 95 96 PropertySlot slot(globalObject); 97 if (!globalObject->getOwnPropertySlot(globalObject, exec, ident, slot) 98 || !slot.isCacheableValue() 99 || !globalObject->structure()->propertyAccessesAreCacheable() 100 || (globalObject->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto() && getOrPut == Put)) { 101 // We know the property will be at global scope, but we don't know how to cache it. 102 ASSERT(!scope->next()); 103 op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, 0, 0); 104 return true; 105 } 106 107 op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), slot.cachedOffset()); 108 return true; 109 } 110 111 op = ResolveOp(Dynamic, 0, 0, 0); 112 return true; 65 113 } 66 114 … … 74 122 } 75 123 76 int JSScope:: localDepth()124 int JSScope::depth() 77 125 { 78 int scopeDepth = 0; 79 ScopeChainIterator iter = this->begin(); 80 ScopeChainIterator end = this->end(); 81 while (!iter->inherits(&JSActivation::s_info)) { 82 ++iter; 83 if (iter == end) 84 break; 85 ++scopeDepth; 86 } 87 return scopeDepth; 126 int depth = 0; 127 for (JSScope* scope = this; scope; scope = scope->next()) 128 ++depth; 129 return depth; 88 130 } 89 131 90 struct LookupResult { 91 JSValue base() const { return m_base; } 92 JSValue value() const { return m_value; } 93 void setBase(JSValue base) { ASSERT(base); m_base = base; } 94 void setValue(JSValue value) { ASSERT(value); m_value = value; } 132 JSValue JSScope::resolve(ExecState* exec, JSScope* scope, const Identifier& ident) 133 { 134 ScopeChainIterator end = scope->end(); 135 ScopeChainIterator it = scope->begin(); 136 while (1) { 137 JSObject* object = it.get(); 95 138 96 private: 97 JSValue m_base; 98 JSValue m_value; 99 }; 139 if (++it == end) // Global scope. 140 return object; 100 141 101 102 static void setPutPropertyAccessOffset(PutToBaseOperation* operation, PropertyOffset offset) 103 { 104 ASSERT(isOutOfLineOffset(offset)); 105 operation->m_offset = offset; 106 operation->m_offsetInButterfly = offsetInButterfly(offset); 107 } 108 109 static bool executeResolveOperations(CallFrame* callFrame, JSScope* scope, const Identifier& propertyName, ResolveOperation* pc, LookupResult& result) 110 { 111 while (true) { 112 switch (pc->m_operation) { 113 case ResolveOperation::Fail: 114 return false; 115 case ResolveOperation::CheckForDynamicEntriesBeforeGlobalScope: { 116 while (JSScope* nextScope = scope->next()) { 117 if (scope->isActivationObject() && scope->structure() != scope->globalObject()->activationStructure()) 118 return false; 119 ASSERT(scope->isNameScopeObject() || scope->isVariableObject() || scope->isGlobalObject()); 120 scope = nextScope; 121 } 122 pc++; 123 break; 124 } 125 case ResolveOperation::SetBaseToUndefined: 126 result.setBase(jsUndefined()); 127 pc++; 128 continue; 129 case ResolveOperation::SetBaseToScope: 130 result.setBase(scope); 131 pc++; 132 continue; 133 case ResolveOperation::ReturnScopeAsBase: 134 result.setBase(scope); 135 return true; 136 case ResolveOperation::SetBaseToGlobal: 137 result.setBase(scope->globalObject()); 138 pc++; 139 continue; 140 case ResolveOperation::SkipScopes: { 141 int count = pc->m_scopesToSkip; 142 while (count--) 143 scope = scope->next(); 144 ASSERT(scope); 145 pc++; 146 continue; 147 } 148 case ResolveOperation::SkipTopScopeNode: 149 if (callFrame->r(pc->m_activationRegister).jsValue()) 150 scope = scope->next(); 151 ASSERT(scope); 152 pc++; 153 continue; 154 case ResolveOperation::GetAndReturnScopedVar: 155 ASSERT(jsCast<JSVariableObject*>(scope)->registerAt(pc->m_offset).get()); 156 result.setValue(jsCast<JSVariableObject*>(scope)->registerAt(pc->m_offset).get()); 157 return true; 158 case ResolveOperation::GetAndReturnGlobalVar: 159 result.setValue(pc->m_registerAddress->get()); 160 return true; 161 case ResolveOperation::GetAndReturnGlobalVarWatchable: 162 result.setValue(pc->m_registerAddress->get()); 163 return true; 164 case ResolveOperation::ReturnGlobalObjectAsBase: 165 result.setBase(callFrame->lexicalGlobalObject()); 166 return true; 167 case ResolveOperation::GetAndReturnGlobalProperty: { 168 JSGlobalObject* globalObject = scope->globalObject(); 169 if (globalObject->structure() == pc->m_structure.get()) { 170 result.setValue(globalObject->getDirect(pc->m_offset)); 171 return true; 172 } 173 174 PropertySlot slot(globalObject); 175 if (!globalObject->getPropertySlot(callFrame, propertyName, slot)) 176 return false; 177 178 JSValue value = slot.getValue(callFrame, propertyName); 179 if (callFrame->hadException()) 180 return false; 181 182 Structure* structure = globalObject->structure(); 183 184 // Don't try to cache prototype lookups 185 if (globalObject != slot.slotBase() || !slot.isCacheableValue() || !structure->propertyAccessesAreCacheable()) { 186 result.setValue(value); 187 return true; 188 } 189 190 pc->m_structure.set(callFrame->vm(), callFrame->codeBlock()->ownerExecutable(), structure); 191 pc->m_offset = slot.cachedOffset(); 192 result.setValue(value); 193 return true; 194 } 195 } 142 if (object->hasProperty(exec, ident)) 143 return object; 196 144 } 197 145 } 198 146 199 template <JSScope::LookupMode mode, JSScope::ReturnValues returnValues> JSObject* JSScope::resolveContainingScopeInternal(CallFrame* callFrame, const Identifier& identifier, PropertySlot& slot, ResolveOperations* operations, PutToBaseOperation* putToBaseOperation, bool)147 ResolveOp JSScope::abstractResolve(ExecState* exec, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, ResolveType unlinkedType) 200 148 { 201 JSScope* scope = callFrame->scope(); 202 ASSERT(scope); 203 int scopeCount = 0; 204 bool seenGenericObjectScope = false; 205 bool requiresDynamicChecks = false; 206 bool skipTopScopeNode = false; 207 int activationRegister = 0; 208 CodeBlock* codeBlock = callFrame->codeBlock(); 209 if (mode == UnknownResolve) { 210 ASSERT(operations->isEmpty()); 211 if (codeBlock->codeType() == FunctionCode && codeBlock->needsActivation()) { 212 activationRegister = codeBlock->activationRegister(); 213 JSValue activation = callFrame->r(activationRegister).jsValue(); 214 215 // If the activation register doesn't match our actual scope, a dynamic 216 // scope has been inserted so we shouldn't skip the top scope node. 217 if (activation == scope) { 218 jsCast<JSActivation*>(activation.asCell())->isDynamicScope(requiresDynamicChecks); 219 if (!requiresDynamicChecks) { 220 ASSERT(jsCast<JSActivation*>(activation.asCell())->symbolTable()->get(identifier.impl()).isNull()); 221 scope = scope->next(); 222 ASSERT(scope); 223 skipTopScopeNode = true; 224 } 225 } else if (!activation) 226 skipTopScopeNode = true; 227 } 228 } else 229 ASSERT(operations->size()); 149 ResolveOp op(Dynamic, 0, 0, 0); 150 if (unlinkedType == Dynamic) 151 return op; 230 152 231 if (codeBlock->codeType() == EvalCode && scope->next()) 232 requiresDynamicChecks = true; 153 size_t depth = 0; 154 bool needsVarInjectionChecks = JSC::needsVarInjectionChecks(unlinkedType); 155 for (; scope; scope = scope->next()) { 156 if (abstractAccess(exec, scope, ident, getOrPut, depth, needsVarInjectionChecks, op)) 157 break; 158 ++depth; 159 } 233 160 234 if (mode == UnknownResolve && putToBaseOperation) 235 putToBaseOperation->m_kind = PutToBaseOperation::Generic; 236 237 do { 238 JSObject* object = JSScope::objectAtScope(scope); 239 slot = PropertySlot(object); 240 241 bool currentScopeNeedsDynamicChecks = false; 242 if (!(scope->isVariableObject() || scope->isNameScopeObject()) || (scope->next() && scope->isDynamicScope(currentScopeNeedsDynamicChecks))) 243 seenGenericObjectScope = true; 244 245 requiresDynamicChecks = requiresDynamicChecks || currentScopeNeedsDynamicChecks; 246 247 if (object->getPropertySlot(callFrame, identifier, slot)) { 248 if (mode == UnknownResolve) { 249 if (seenGenericObjectScope) 250 goto fail; 251 if (putToBaseOperation) 252 putToBaseOperation->m_isDynamic = requiresDynamicChecks; 253 if (!scope->next()) { 254 // Global lookup of some kind 255 JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(scope); 256 SymbolTableEntry entry = globalObject->symbolTable()->get(identifier.impl()); 257 if (!entry.isNull()) { 258 if (requiresDynamicChecks) 259 operations->append(ResolveOperation::checkForDynamicEntriesBeforeGlobalScope()); 260 261 if (putToBaseOperation) { 262 putToBaseOperation->m_isDynamic = requiresDynamicChecks; 263 if (entry.isReadOnly()) 264 putToBaseOperation->m_kind = PutToBaseOperation::Readonly; 265 else if (entry.couldBeWatched()) { 266 putToBaseOperation->m_kind = PutToBaseOperation::GlobalVariablePutChecked; 267 putToBaseOperation->m_predicatePointer = entry.addressOfIsWatched(); 268 } else 269 putToBaseOperation->m_kind = PutToBaseOperation::GlobalVariablePut; 270 putToBaseOperation->m_registerAddress = &globalObject->registerAt(entry.getIndex()); 271 } 272 // Override custom accessor behaviour that the DOM introduces for some 273 // event handlers declared on function declarations. 274 if (!requiresDynamicChecks) 275 slot.setValue(globalObject, globalObject->registerAt(entry.getIndex()).get()); 276 switch (returnValues) { 277 case ReturnValue: 278 ASSERT(!putToBaseOperation); 279 operations->append(ResolveOperation::getAndReturnGlobalVar(&globalObject->registerAt(entry.getIndex()), entry.couldBeWatched())); 280 break; 281 case ReturnBase: 282 ASSERT(putToBaseOperation); 283 operations->append(ResolveOperation::returnGlobalObjectAsBase()); 284 break; 285 case ReturnBaseAndValue: 286 ASSERT(putToBaseOperation); 287 operations->append(ResolveOperation::setBaseToGlobal()); 288 operations->append(ResolveOperation::getAndReturnGlobalVar(&globalObject->registerAt(entry.getIndex()), entry.couldBeWatched())); 289 break; 290 case ReturnThisAndValue: 291 ASSERT(!putToBaseOperation); 292 operations->append(ResolveOperation::setBaseToUndefined()); 293 operations->append(ResolveOperation::getAndReturnGlobalVar(&globalObject->registerAt(entry.getIndex()), entry.couldBeWatched())); 294 break; 295 } 296 } else { 297 if (!slot.isCacheableValue() || slot.slotBase() != globalObject) 298 goto fail; 299 300 if (requiresDynamicChecks) 301 operations->append(ResolveOperation::checkForDynamicEntriesBeforeGlobalScope()); 302 303 if (putToBaseOperation) { 304 ConcurrentJITLocker locker(callFrame->codeBlock()->m_lock); 305 306 putToBaseOperation->m_isDynamic = requiresDynamicChecks; 307 putToBaseOperation->m_kind = PutToBaseOperation::GlobalPropertyPut; 308 putToBaseOperation->m_structure.set(callFrame->vm(), callFrame->codeBlock()->ownerExecutable(), globalObject->structure()); 309 setPutPropertyAccessOffset(putToBaseOperation, slot.cachedOffset()); 310 } 311 switch (returnValues) { 312 case ReturnValue: 313 ASSERT(!putToBaseOperation); 314 operations->append(ResolveOperation::getAndReturnGlobalProperty()); 315 break; 316 case ReturnBase: 317 ASSERT(putToBaseOperation); 318 operations->append(ResolveOperation::returnGlobalObjectAsBase()); 319 break; 320 case ReturnBaseAndValue: 321 ASSERT(putToBaseOperation); 322 operations->append(ResolveOperation::setBaseToGlobal()); 323 operations->append(ResolveOperation::getAndReturnGlobalProperty()); 324 break; 325 case ReturnThisAndValue: 326 ASSERT(!putToBaseOperation); 327 operations->append(ResolveOperation::setBaseToUndefined()); 328 operations->append(ResolveOperation::getAndReturnGlobalProperty()); 329 break; 330 } 331 } 332 return object; 333 } 334 if (!requiresDynamicChecks) { 335 // Normal lexical lookup 336 JSVariableObject* variableObject = jsCast<JSVariableObject*>(scope); 337 ASSERT(variableObject); 338 ASSERT(variableObject->symbolTable()); 339 SymbolTableEntry entry = variableObject->symbolTable()->get(identifier.impl()); 340 // Defend against the variable being actually inserted by eval. 341 if (entry.isNull()) { 342 ASSERT(!jsDynamicCast<JSNameScope*>(variableObject)); 343 goto fail; 344 } 345 // If we're getting the 'arguments' then give up on life. 346 if (identifier == callFrame->propertyNames().arguments) 347 goto fail; 348 349 if (putToBaseOperation) { 350 ConcurrentJITLocker locker(callFrame->codeBlock()->m_lock); 351 352 putToBaseOperation->m_kind = entry.isReadOnly() ? PutToBaseOperation::Readonly : PutToBaseOperation::VariablePut; 353 putToBaseOperation->m_structure.set(callFrame->vm(), callFrame->codeBlock()->ownerExecutable(), callFrame->lexicalGlobalObject()->activationStructure()); 354 putToBaseOperation->m_offset = entry.getIndex(); 355 putToBaseOperation->m_scopeDepth = (skipTopScopeNode ? 1 : 0) + scopeCount; 356 } 357 358 if (skipTopScopeNode) 359 operations->append(ResolveOperation::skipTopScopeNode(activationRegister)); 360 361 operations->append(ResolveOperation::skipScopes(scopeCount)); 362 switch (returnValues) { 363 case ReturnBaseAndValue: 364 operations->append(ResolveOperation::setBaseToScope()); 365 operations->append(ResolveOperation::getAndReturnScopedVar(entry.getIndex())); 366 break; 367 368 case ReturnBase: 369 operations->append(ResolveOperation::returnScopeAsBase()); 370 break; 371 372 case ReturnThisAndValue: 373 operations->append(ResolveOperation::setBaseToUndefined()); 374 // fallthrough 375 case ReturnValue: 376 operations->append(ResolveOperation::getAndReturnScopedVar(entry.getIndex())); 377 break; 378 } 379 return object; 380 } 381 fail: 382 if (!operations->size()) 383 operations->append(ResolveOperation::resolveFail()); 384 } 385 return object; 386 } 387 scopeCount++; 388 } while ((scope = scope->next())); 389 390 if (mode == UnknownResolve) { 391 ASSERT(operations->isEmpty()); 392 if (seenGenericObjectScope) { 393 operations->append(ResolveOperation::resolveFail()); 394 return 0; 395 } 396 if (putToBaseOperation) { 397 putToBaseOperation->m_isDynamic = requiresDynamicChecks; 398 putToBaseOperation->m_kind = PutToBaseOperation::GlobalPropertyPut; 399 putToBaseOperation->m_structure.clear(); 400 putToBaseOperation->m_offset = -1; 401 } 402 if (requiresDynamicChecks) 403 operations->append(ResolveOperation::checkForDynamicEntriesBeforeGlobalScope()); 404 switch (returnValues) { 405 case ReturnValue: 406 ASSERT(!putToBaseOperation); 407 operations->append(ResolveOperation::getAndReturnGlobalProperty()); 408 break; 409 case ReturnBase: 410 ASSERT(putToBaseOperation); 411 operations->append(ResolveOperation::returnGlobalObjectAsBase()); 412 break; 413 case ReturnBaseAndValue: 414 ASSERT(putToBaseOperation); 415 operations->append(ResolveOperation::setBaseToGlobal()); 416 operations->append(ResolveOperation::getAndReturnGlobalProperty()); 417 break; 418 case ReturnThisAndValue: 419 ASSERT(!putToBaseOperation); 420 operations->append(ResolveOperation::setBaseToUndefined()); 421 operations->append(ResolveOperation::getAndReturnGlobalProperty()); 422 break; 423 } 424 } 425 return 0; 161 return op; 426 162 } 427 163 428 template <JSScope::ReturnValues returnValues> JSObject* JSScope::resolveContainingScope(CallFrame* callFrame, const Identifier& identifier, PropertySlot& slot, ResolveOperations* operations, PutToBaseOperation* putToBaseOperation, bool isStrict)429 {430 if (operations->size())431 return resolveContainingScopeInternal<KnownResolve, returnValues>(callFrame, identifier, slot, operations, putToBaseOperation, isStrict);432 JSObject* result = resolveContainingScopeInternal<UnknownResolve, returnValues>(callFrame, identifier, slot, operations, putToBaseOperation, isStrict);433 operations->shrinkToFit();434 return result;435 }436 437 JSValue JSScope::resolve(CallFrame* callFrame, const Identifier& identifier, ResolveOperations* operations)438 {439 ASSERT(operations);440 LookupResult fastResult;441 if (operations->size() && executeResolveOperations(callFrame, callFrame->scope(), identifier, operations->data(), fastResult)) {442 ASSERT(fastResult.value());443 ASSERT(!callFrame->hadException());444 return fastResult.value();445 }446 447 if (callFrame->hadException())448 return JSValue();449 450 PropertySlot slot;451 if (JSScope::resolveContainingScope<ReturnValue>(callFrame, identifier, slot, operations, 0, false)) {452 ASSERT(operations->size());453 return slot.getValue(callFrame, identifier);454 }455 ASSERT(operations->size());456 457 return throwError(callFrame, createUndefinedVariableError(callFrame, identifier));458 }459 460 JSValue JSScope::resolveBase(CallFrame* callFrame, const Identifier& identifier, bool isStrict, ResolveOperations* operations, PutToBaseOperation* putToBaseOperations)461 {462 ASSERT(operations);463 ASSERT_UNUSED(putToBaseOperations, putToBaseOperations);464 LookupResult fastResult;465 if (operations->size() && executeResolveOperations(callFrame, callFrame->scope(), identifier, operations->data(), fastResult)) {466 ASSERT(fastResult.base());467 ASSERT(!callFrame->hadException());468 return fastResult.base();469 }470 471 if (callFrame->hadException())472 return JSValue();473 474 PropertySlot slot;475 if (JSObject* base = JSScope::resolveContainingScope<ReturnBase>(callFrame, identifier, slot, operations, putToBaseOperations, isStrict)) {476 ASSERT(operations->size());477 return base;478 }479 480 if (!isStrict)481 return callFrame->lexicalGlobalObject();482 483 return throwError(callFrame, createErrorForInvalidGlobalAssignment(callFrame, identifier.string()));484 }485 486 JSValue JSScope::resolveWithBase(CallFrame* callFrame, const Identifier& identifier, Register* base, ResolveOperations* operations, PutToBaseOperation* putToBaseOperations)487 {488 ASSERT(operations);489 ASSERT_UNUSED(putToBaseOperations, putToBaseOperations);490 LookupResult fastResult;491 if (operations->size() && executeResolveOperations(callFrame, callFrame->scope(), identifier, operations->data(), fastResult)) {492 ASSERT(fastResult.base());493 ASSERT(fastResult.value());494 ASSERT(!callFrame->hadException());495 *base = fastResult.base();496 return fastResult.value();497 }498 499 if (callFrame->hadException())500 return JSValue();501 502 PropertySlot slot;503 if (JSObject* propertyBase = JSScope::resolveContainingScope<ReturnBaseAndValue>(callFrame, identifier, slot, operations, putToBaseOperations, false)) {504 ASSERT(operations->size());505 JSValue value = slot.getValue(callFrame, identifier);506 if (callFrame->vm().exception)507 return JSValue();508 509 *base = propertyBase;510 return value;511 }512 ASSERT(operations->size());513 514 return throwError(callFrame, createUndefinedVariableError(callFrame, identifier));515 }516 517 JSValue JSScope::resolveWithThis(CallFrame* callFrame, const Identifier& identifier, Register* base, ResolveOperations* operations)518 {519 ASSERT(operations);520 LookupResult fastResult;521 if (operations->size() && executeResolveOperations(callFrame, callFrame->scope(), identifier, operations->data(), fastResult)) {522 ASSERT(fastResult.base());523 ASSERT(fastResult.value());524 ASSERT(!callFrame->hadException());525 *base = fastResult.base();526 return fastResult.value();527 }528 529 if (callFrame->hadException())530 return JSValue();531 532 PropertySlot slot;533 if (JSObject* propertyBase = JSScope::resolveContainingScope<ReturnThisAndValue>(callFrame, identifier, slot, operations, 0, false)) {534 ASSERT(operations->size());535 JSValue value = slot.getValue(callFrame, identifier);536 if (callFrame->vm().exception)537 return JSValue();538 ASSERT(value);539 *base = JSValue(propertyBase);540 return value;541 }542 ASSERT(operations->size());543 544 return throwError(callFrame, createUndefinedVariableError(callFrame, identifier));545 }546 547 void JSScope::resolvePut(CallFrame* callFrame, JSValue base, const Identifier& property, JSValue value, PutToBaseOperation* operation)548 {549 ASSERT_UNUSED(operation, operation);550 ASSERT(base);551 ASSERT(value);552 switch (operation->m_kind) {553 case PutToBaseOperation::Uninitialised:554 CRASH();555 556 case PutToBaseOperation::Readonly:557 return;558 559 case PutToBaseOperation::GlobalVariablePutChecked:560 if (*operation->m_predicatePointer)561 goto genericHandler;562 case PutToBaseOperation::GlobalVariablePut:563 if (operation->m_isDynamic) {564 JSObject* baseObject = jsCast<JSObject*>(base);565 if (baseObject != callFrame->lexicalGlobalObject()) {566 if (baseObject->isGlobalObject())567 ASSERT(!jsCast<JSGlobalObject*>(baseObject)->assertRegisterIsInThisObject(operation->m_registerAddress));568 goto genericHandler;569 }570 }571 operation->m_registerAddress->set(callFrame->vm(), base.asCell(), value);572 return;573 574 case PutToBaseOperation::VariablePut: {575 if (operation->m_isDynamic) {576 JSObject* baseObject = jsCast<JSObject*>(base);577 if (baseObject->structure() != operation->m_structure.get())578 goto genericHandler;579 }580 JSVariableObject* variableObject = jsCast<JSVariableObject*>(base);581 variableObject->registerAt(operation->m_offset).set(callFrame->vm(), variableObject, value);582 return;583 }584 585 case PutToBaseOperation::GlobalPropertyPut: {586 JSObject* object = jsCast<JSObject*>(base);587 if (operation->m_structure.get() != object->structure())588 break;589 object->putDirect(callFrame->vm(), operation->m_offset, value);590 return;591 }592 593 genericHandler:594 case PutToBaseOperation::Generic:595 PutPropertySlot slot(operation->m_isStrict);596 base.put(callFrame, property, value, slot);597 return;598 }599 ASSERT(operation->m_kind == PutToBaseOperation::GlobalPropertyPut);600 PutPropertySlot slot(operation->m_isStrict);601 base.put(callFrame, property, value, slot);602 if (!slot.isCacheable())603 return;604 if (callFrame->hadException())605 return;606 JSObject* baseObject = jsCast<JSObject*>(base);607 if (!baseObject->structure()->propertyAccessesAreCacheable())608 return;609 if (slot.base() != callFrame->lexicalGlobalObject())610 return;611 if (slot.base() != baseObject)612 return;613 ASSERT(!baseObject->hasInlineStorage());614 ConcurrentJITLocker locker(callFrame->codeBlock()->m_lock);615 616 operation->m_structure.set(callFrame->vm(), callFrame->codeBlock()->ownerExecutable(), baseObject->structure());617 setPutPropertyAccessOffset(operation, slot.cachedOffset());618 return;619 }620 621 JSValue JSScope::resolveGlobal(CallFrame* callFrame, const Identifier& identifier, JSGlobalObject* globalObject, ResolveOperation* resolveOperation)622 {623 ASSERT(resolveOperation);624 ASSERT(resolveOperation->m_operation == ResolveOperation::GetAndReturnGlobalProperty);625 ASSERT_UNUSED(globalObject, callFrame->lexicalGlobalObject() == globalObject);626 627 LookupResult fastResult;628 if (executeResolveOperations(callFrame, callFrame->scope(), identifier, resolveOperation, fastResult)) {629 ASSERT(fastResult.value());630 ASSERT(!callFrame->hadException());631 return fastResult.value();632 }633 634 if (callFrame->hadException())635 return JSValue();636 637 return throwError(callFrame, createUndefinedVariableError(callFrame, identifier));638 }639 640 641 164 } // namespace JSC
Note:
See TracChangeset
for help on using the changeset viewer.