2  * Copyright (C) 2012 Apple Inc. All Rights Reserved. 
   4  * Redistribution and use in source and binary forms, with or without 
   5  * modification, are permitted provided that the following conditions 
   7  * 1. Redistributions of source code must retain the above copyright 
   8  *    notice, this list of conditions and the following disclaimer. 
   9  * 2. Redistributions in binary form must reproduce the above copyright 
  10  *    notice, this list of conditions and the following disclaimer in the 
  11  *    documentation and/or other materials provided with the distribution. 
  13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 
  14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR 
  17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
  19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
  21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
  22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
  23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
  29 #include "JSActivation.h" 
  30 #include "JSGlobalObject.h" 
  31 #include "JSNameScope.h" 
  32 #include "JSWithScope.h" 
  33 #include "Operations.h" 
  37 ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSScope
); 
  39 void JSScope::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
) 
  41     JSScope
* thisObject 
= jsCast
<JSScope
*>(cell
); 
  42     ASSERT_GC_OBJECT_INHERITS(thisObject
, &s_info
); 
  43     COMPILE_ASSERT(StructureFlags 
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
); 
  44     ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren()); 
  46     Base::visitChildren(thisObject
, visitor
); 
  47     visitor
.append(&thisObject
->m_next
); 
  50 bool JSScope::isDynamicScope(bool& requiresDynamicChecks
) const 
  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
); 
  60         RELEASE_ASSERT_NOT_REACHED(); 
  67 JSObject
* JSScope::objectAtScope(JSScope
* scope
) 
  69     JSObject
* object 
= scope
; 
  70     if (object
->structure()->typeInfo().type() == WithScopeType
) 
  71         return jsCast
<JSWithScope
*>(object
)->object(); 
  76 int JSScope::localDepth() 
  79     ScopeChainIterator iter 
= this->begin(); 
  80     ScopeChainIterator end 
= this->end(); 
  81     while (!iter
->inherits(&JSActivation::s_info
)) { 
  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
; } 
 102 static void setPutPropertyAccessOffset(PutToBaseOperation
* operation
, PropertyOffset offset
) 
 104     ASSERT(isOutOfLineOffset(offset
)); 
 105     operation
->m_offset 
= offset
; 
 106     operation
->m_offsetInButterfly 
= offsetInButterfly(offset
); 
 109 static bool executeResolveOperations(CallFrame
* callFrame
, JSScope
* scope
, const Identifier
& propertyName
, ResolveOperation
* pc
, LookupResult
& result
) 
 112         switch (pc
->m_operation
) { 
 113         case ResolveOperation::Fail
: 
 115         case ResolveOperation::CheckForDynamicEntriesBeforeGlobalScope
: { 
 116             while (JSScope
* nextScope 
= scope
->next()) { 
 117                 if (scope
->isActivationObject() && scope
->structure() != scope
->globalObject()->activationStructure()) 
 119                 ASSERT(scope
->isNameScopeObject() || scope
->isVariableObject() || scope
->isGlobalObject()); 
 125         case ResolveOperation::SetBaseToUndefined
: 
 126             result
.setBase(jsUndefined()); 
 129         case ResolveOperation::SetBaseToScope
: 
 130             result
.setBase(scope
); 
 133         case ResolveOperation::ReturnScopeAsBase
: 
 134             result
.setBase(scope
); 
 136         case ResolveOperation::SetBaseToGlobal
: 
 137             result
.setBase(scope
->globalObject()); 
 140         case ResolveOperation::SkipScopes
: { 
 141             int count 
= pc
->m_scopesToSkip
; 
 143                 scope 
= scope
->next(); 
 148         case ResolveOperation::SkipTopScopeNode
: 
 149             if (callFrame
->r(pc
->m_activationRegister
).jsValue()) 
 150                 scope 
= scope
->next(); 
 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()); 
 158         case ResolveOperation::GetAndReturnGlobalVar
: 
 159             result
.setValue(pc
->m_registerAddress
->get()); 
 161         case ResolveOperation::GetAndReturnGlobalVarWatchable
: 
 162             result
.setValue(pc
->m_registerAddress
->get()); 
 164         case ResolveOperation::ReturnGlobalObjectAsBase
: 
 165             result
.setBase(callFrame
->lexicalGlobalObject()); 
 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
)); 
 174             PropertySlot 
slot(globalObject
); 
 175             if (!globalObject
->getPropertySlot(callFrame
, propertyName
, slot
)) 
 178             JSValue value 
= slot
.getValue(callFrame
, propertyName
); 
 179             if (callFrame
->hadException()) 
 182             Structure
* structure 
= globalObject
->structure(); 
 184             // Don't try to cache prototype lookups 
 185             if (globalObject 
!= slot
.slotBase() || !slot
.isCacheableValue() || !structure
->propertyAccessesAreCacheable()) { 
 186                 result
.setValue(value
); 
 190             pc
->m_structure
.set(callFrame
->vm(), callFrame
->codeBlock()->ownerExecutable(), structure
); 
 191             pc
->m_offset 
= slot
.cachedOffset(); 
 192             result
.setValue(value
); 
 199 template <JSScope::LookupMode mode
, JSScope::ReturnValues returnValues
> JSObject
* JSScope::resolveContainingScopeInternal(CallFrame
* callFrame
, const Identifier
& identifier
, PropertySlot
& slot
, Vector
<ResolveOperation
>* operations
, PutToBaseOperation
* putToBaseOperation
, bool ) 
 201     JSScope
* scope 
= callFrame
->scope(); 
 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(); 
 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(); 
 223                     skipTopScopeNode 
= true; 
 225             } else if (!activation
) 
 226                 skipTopScopeNode 
= true; 
 229         ASSERT(operations
->size()); 
 231     if (codeBlock
->codeType() == EvalCode 
&& scope
->next()) 
 232         requiresDynamicChecks 
= true; 
 234     if (mode 
== UnknownResolve 
&& putToBaseOperation
) 
 235         putToBaseOperation
->m_kind 
= PutToBaseOperation::Generic
; 
 238         JSObject
* object 
= JSScope::objectAtScope(scope
); 
 239         slot 
= PropertySlot(object
); 
 241         bool currentScopeNeedsDynamicChecks 
= false; 
 242         if (!(scope
->isVariableObject() || scope
->isNameScopeObject()) || (scope
->next() && scope
->isDynamicScope(currentScopeNeedsDynamicChecks
))) 
 243             seenGenericObjectScope 
= true; 
 245         requiresDynamicChecks 
= requiresDynamicChecks 
|| currentScopeNeedsDynamicChecks
; 
 247         if (object
->getPropertySlot(callFrame
, identifier
, slot
)) { 
 248             if (mode 
== UnknownResolve
) { 
 249                 if (seenGenericObjectScope
) 
 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()); 
 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(); 
 269                                 putToBaseOperation
->m_kind 
= PutToBaseOperation::GlobalVariablePut
; 
 270                             putToBaseOperation
->m_registerAddress 
= &globalObject
->registerAt(entry
.getIndex()); 
 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
) { 
 278                             ASSERT(!putToBaseOperation
); 
 279                             operations
->append(ResolveOperation::getAndReturnGlobalVar(&globalObject
->registerAt(entry
.getIndex()), entry
.couldBeWatched())); 
 282                             ASSERT(putToBaseOperation
); 
 283                             operations
->append(ResolveOperation::returnGlobalObjectAsBase()); 
 285                         case ReturnBaseAndValue
: 
 286                             ASSERT(putToBaseOperation
); 
 287                             operations
->append(ResolveOperation::setBaseToGlobal()); 
 288                             operations
->append(ResolveOperation::getAndReturnGlobalVar(&globalObject
->registerAt(entry
.getIndex()), entry
.couldBeWatched())); 
 290                         case ReturnThisAndValue
: 
 291                             ASSERT(!putToBaseOperation
); 
 292                             operations
->append(ResolveOperation::setBaseToUndefined()); 
 293                             operations
->append(ResolveOperation::getAndReturnGlobalVar(&globalObject
->registerAt(entry
.getIndex()), entry
.couldBeWatched())); 
 297                         if (!slot
.isCacheableValue() || slot
.slotBase() != globalObject
) 
 300                         if (requiresDynamicChecks
) 
 301                             operations
->append(ResolveOperation::checkForDynamicEntriesBeforeGlobalScope()); 
 303                         if (putToBaseOperation
) { 
 304                             putToBaseOperation
->m_isDynamic 
= requiresDynamicChecks
; 
 305                             putToBaseOperation
->m_kind 
= PutToBaseOperation::GlobalPropertyPut
; 
 306                             putToBaseOperation
->m_structure
.set(callFrame
->vm(), callFrame
->codeBlock()->ownerExecutable(), globalObject
->structure()); 
 307                             setPutPropertyAccessOffset(putToBaseOperation
, slot
.cachedOffset()); 
 309                         switch (returnValues
) { 
 311                             ASSERT(!putToBaseOperation
); 
 312                             operations
->append(ResolveOperation::getAndReturnGlobalProperty()); 
 315                             ASSERT(putToBaseOperation
); 
 316                             operations
->append(ResolveOperation::returnGlobalObjectAsBase()); 
 318                         case ReturnBaseAndValue
: 
 319                             ASSERT(putToBaseOperation
); 
 320                             operations
->append(ResolveOperation::setBaseToGlobal()); 
 321                             operations
->append(ResolveOperation::getAndReturnGlobalProperty()); 
 323                         case ReturnThisAndValue
: 
 324                             ASSERT(!putToBaseOperation
); 
 325                             operations
->append(ResolveOperation::setBaseToUndefined()); 
 326                             operations
->append(ResolveOperation::getAndReturnGlobalProperty()); 
 332                 if (!requiresDynamicChecks
) { 
 333                     // Normal lexical lookup 
 334                     JSVariableObject
* variableObject 
= jsCast
<JSVariableObject
*>(scope
); 
 335                     ASSERT(variableObject
); 
 336                     ASSERT(variableObject
->symbolTable()); 
 337                     SymbolTableEntry entry 
= variableObject
->symbolTable()->get(identifier
.impl()); 
 338                     // Defend against the variable being actually inserted by eval. 
 339                     if (entry
.isNull()) { 
 340                         ASSERT(!jsDynamicCast
<JSNameScope
*>(variableObject
)); 
 343                     // If we're getting the 'arguments' then give up on life. 
 344                     if (identifier 
== callFrame
->propertyNames().arguments
) 
 347                     if (putToBaseOperation
) { 
 348                         putToBaseOperation
->m_kind 
= entry
.isReadOnly() ? PutToBaseOperation::Readonly 
: PutToBaseOperation::VariablePut
; 
 349                         putToBaseOperation
->m_structure
.set(callFrame
->vm(), callFrame
->codeBlock()->ownerExecutable(), callFrame
->lexicalGlobalObject()->activationStructure()); 
 350                         putToBaseOperation
->m_offset 
= entry
.getIndex(); 
 351                         putToBaseOperation
->m_scopeDepth 
= (skipTopScopeNode 
? 1 : 0) + scopeCount
; 
 354                     if (skipTopScopeNode
) 
 355                         operations
->append(ResolveOperation::skipTopScopeNode(activationRegister
)); 
 357                     operations
->append(ResolveOperation::skipScopes(scopeCount
)); 
 358                     switch (returnValues
) { 
 359                     case ReturnBaseAndValue
: 
 360                         operations
->append(ResolveOperation::setBaseToScope()); 
 361                         operations
->append(ResolveOperation::getAndReturnScopedVar(entry
.getIndex())); 
 365                         operations
->append(ResolveOperation::returnScopeAsBase()); 
 368                     case ReturnThisAndValue
: 
 369                         operations
->append(ResolveOperation::setBaseToUndefined()); 
 372                         operations
->append(ResolveOperation::getAndReturnScopedVar(entry
.getIndex())); 
 378                 if (!operations
->size()) 
 379                     operations
->append(ResolveOperation::resolveFail()); 
 384     } while ((scope 
= scope
->next())); 
 386     if (mode 
== UnknownResolve
) { 
 387         ASSERT(operations
->isEmpty()); 
 388         if (seenGenericObjectScope
) { 
 389             operations
->append(ResolveOperation::resolveFail()); 
 392         if (putToBaseOperation
) { 
 393             putToBaseOperation
->m_isDynamic 
= requiresDynamicChecks
; 
 394             putToBaseOperation
->m_kind 
= PutToBaseOperation::GlobalPropertyPut
; 
 395             putToBaseOperation
->m_structure
.clear(); 
 396             putToBaseOperation
->m_offset 
= -1; 
 398         if (requiresDynamicChecks
) 
 399             operations
->append(ResolveOperation::checkForDynamicEntriesBeforeGlobalScope()); 
 400         switch (returnValues
) { 
 402             ASSERT(!putToBaseOperation
); 
 403             operations
->append(ResolveOperation::getAndReturnGlobalProperty()); 
 406             ASSERT(putToBaseOperation
); 
 407             operations
->append(ResolveOperation::returnGlobalObjectAsBase()); 
 409         case ReturnBaseAndValue
: 
 410             ASSERT(putToBaseOperation
); 
 411             operations
->append(ResolveOperation::setBaseToGlobal()); 
 412             operations
->append(ResolveOperation::getAndReturnGlobalProperty()); 
 414         case ReturnThisAndValue
: 
 415             ASSERT(!putToBaseOperation
); 
 416             operations
->append(ResolveOperation::setBaseToUndefined()); 
 417             operations
->append(ResolveOperation::getAndReturnGlobalProperty()); 
 424 template <JSScope::ReturnValues returnValues
> JSObject
* JSScope::resolveContainingScope(CallFrame
* callFrame
, const Identifier
& identifier
, PropertySlot
& slot
, Vector
<ResolveOperation
>* operations
, PutToBaseOperation
* putToBaseOperation
, bool isStrict
) 
 426     if (operations
->size()) 
 427         return resolveContainingScopeInternal
<KnownResolve
, returnValues
>(callFrame
, identifier
, slot
, operations
, putToBaseOperation
, isStrict
); 
 428     JSObject
* result 
= resolveContainingScopeInternal
<UnknownResolve
, returnValues
>(callFrame
, identifier
, slot
, operations
, putToBaseOperation
, isStrict
); 
 429     operations
->shrinkToFit(); 
 433 JSValue 
JSScope::resolve(CallFrame
* callFrame
, const Identifier
& identifier
, ResolveOperations
* operations
) 
 436     LookupResult fastResult
; 
 437     if (operations
->size() && executeResolveOperations(callFrame
, callFrame
->scope(), identifier
, operations
->data(), fastResult
)) { 
 438         ASSERT(fastResult
.value()); 
 439         ASSERT(!callFrame
->hadException()); 
 440         return fastResult
.value(); 
 443     if (callFrame
->hadException()) 
 447     if (JSScope::resolveContainingScope
<ReturnValue
>(callFrame
, identifier
, slot
, operations
, 0, false)) { 
 448         ASSERT(operations
->size()); 
 449         return slot
.getValue(callFrame
, identifier
); 
 451     ASSERT(operations
->size()); 
 453     return throwError(callFrame
, createUndefinedVariableError(callFrame
, identifier
)); 
 456 JSValue 
JSScope::resolveBase(CallFrame
* callFrame
, const Identifier
& identifier
, bool isStrict
, ResolveOperations
* operations
, PutToBaseOperation
* putToBaseOperations
) 
 459     ASSERT_UNUSED(putToBaseOperations
, putToBaseOperations
); 
 460     LookupResult fastResult
; 
 461     if (operations
->size() && executeResolveOperations(callFrame
, callFrame
->scope(), identifier
, operations
->data(), fastResult
)) { 
 462         ASSERT(fastResult
.base()); 
 463         ASSERT(!callFrame
->hadException()); 
 464         return fastResult
.base(); 
 467     if (callFrame
->hadException()) 
 471     if (JSObject
* base 
= JSScope::resolveContainingScope
<ReturnBase
>(callFrame
, identifier
, slot
, operations
, putToBaseOperations
, isStrict
)) { 
 472         ASSERT(operations
->size()); 
 477         return callFrame
->lexicalGlobalObject(); 
 479     return throwError(callFrame
, createErrorForInvalidGlobalAssignment(callFrame
, identifier
.string())); 
 482 JSValue 
JSScope::resolveWithBase(CallFrame
* callFrame
, const Identifier
& identifier
, Register
* base
, ResolveOperations
* operations
, PutToBaseOperation
* putToBaseOperations
) 
 485     ASSERT_UNUSED(putToBaseOperations
, putToBaseOperations
); 
 486     LookupResult fastResult
; 
 487     if (operations
->size() && executeResolveOperations(callFrame
, callFrame
->scope(), identifier
, operations
->data(), fastResult
)) { 
 488         ASSERT(fastResult
.base()); 
 489         ASSERT(fastResult
.value()); 
 490         ASSERT(!callFrame
->hadException()); 
 491         *base 
= fastResult
.base(); 
 492         return fastResult
.value(); 
 495     if (callFrame
->hadException()) 
 499     if (JSObject
* propertyBase 
= JSScope::resolveContainingScope
<ReturnBaseAndValue
>(callFrame
, identifier
, slot
, operations
, putToBaseOperations
, false)) { 
 500         ASSERT(operations
->size()); 
 501         JSValue value 
= slot
.getValue(callFrame
, identifier
); 
 502         if (callFrame
->vm().exception
) 
 505         *base 
= propertyBase
; 
 508     ASSERT(operations
->size()); 
 510     return throwError(callFrame
, createUndefinedVariableError(callFrame
, identifier
)); 
 513 JSValue 
JSScope::resolveWithThis(CallFrame
* callFrame
, const Identifier
& identifier
, Register
* base
, ResolveOperations
* operations
) 
 516     LookupResult fastResult
; 
 517     if (operations
->size() && executeResolveOperations(callFrame
, callFrame
->scope(), identifier
, operations
->data(), fastResult
)) { 
 518         ASSERT(fastResult
.base()); 
 519         ASSERT(fastResult
.value()); 
 520         ASSERT(!callFrame
->hadException()); 
 521         *base 
= fastResult
.base(); 
 522         return fastResult
.value(); 
 525     if (callFrame
->hadException()) 
 529     if (JSObject
* propertyBase 
= JSScope::resolveContainingScope
<ReturnThisAndValue
>(callFrame
, identifier
, slot
, operations
, 0, false)) { 
 530         ASSERT(operations
->size()); 
 531         JSValue value 
= slot
.getValue(callFrame
, identifier
); 
 532         if (callFrame
->vm().exception
) 
 535         *base 
= propertyBase
->structure()->typeInfo().isEnvironmentRecord() ? jsUndefined() : JSValue(propertyBase
); 
 538     ASSERT(operations
->size()); 
 540     return throwError(callFrame
, createUndefinedVariableError(callFrame
, identifier
)); 
 543 void JSScope::resolvePut(CallFrame
* callFrame
, JSValue base
, const Identifier
& property
, JSValue value
, PutToBaseOperation
* operation
) 
 545     ASSERT_UNUSED(operation
, operation
); 
 548     switch (operation
->m_kind
) { 
 549     case PutToBaseOperation::Uninitialised
: 
 552     case PutToBaseOperation::Readonly
: 
 555     case PutToBaseOperation::GlobalVariablePutChecked
: 
 556         if (*operation
->m_predicatePointer
) 
 558     case PutToBaseOperation::GlobalVariablePut
: 
 559         if (operation
->m_isDynamic
) { 
 560             JSObject
* baseObject 
= jsCast
<JSObject
*>(base
); 
 561             if (baseObject 
!= callFrame
->lexicalGlobalObject()) { 
 562                 if (baseObject
->isGlobalObject()) 
 563                     ASSERT(!jsCast
<JSGlobalObject
*>(baseObject
)->assertRegisterIsInThisObject(operation
->m_registerAddress
)); 
 567         operation
->m_registerAddress
->set(callFrame
->vm(), base
.asCell(), value
); 
 570     case PutToBaseOperation::VariablePut
: { 
 571         if (operation
->m_isDynamic
) { 
 572             JSObject
* baseObject 
= jsCast
<JSObject
*>(base
); 
 573             if (baseObject
->structure() != operation
->m_structure
.get()) 
 576         JSVariableObject
* variableObject 
= jsCast
<JSVariableObject
*>(base
); 
 577         variableObject
->registerAt(operation
->m_offset
).set(callFrame
->vm(), variableObject
, value
); 
 581     case PutToBaseOperation::GlobalPropertyPut
: { 
 582         JSObject
* object 
= jsCast
<JSObject
*>(base
); 
 583         if (operation
->m_structure
.get() != object
->structure()) 
 585         object
->putDirect(callFrame
->vm(), operation
->m_offset
, value
); 
 590     case PutToBaseOperation::Generic
: 
 591         PutPropertySlot 
slot(operation
->m_isStrict
); 
 592         base
.put(callFrame
, property
, value
, slot
); 
 595     ASSERT(operation
->m_kind 
== PutToBaseOperation::GlobalPropertyPut
); 
 596     PutPropertySlot 
slot(operation
->m_isStrict
); 
 597     base
.put(callFrame
, property
, value
, slot
); 
 598     if (!slot
.isCacheable()) 
 600     if (callFrame
->hadException()) 
 602     JSObject
* baseObject 
= jsCast
<JSObject
*>(base
); 
 603     if (!baseObject
->structure()->propertyAccessesAreCacheable()) 
 605     if (slot
.base() != callFrame
->lexicalGlobalObject()) 
 607     if (slot
.base() != baseObject
) 
 609     ASSERT(!baseObject
->hasInlineStorage()); 
 610     operation
->m_structure
.set(callFrame
->vm(), callFrame
->codeBlock()->ownerExecutable(), baseObject
->structure()); 
 611     setPutPropertyAccessOffset(operation
, slot
.cachedOffset()); 
 615 JSValue 
JSScope::resolveGlobal(CallFrame
* callFrame
, const Identifier
& identifier
, JSGlobalObject
* globalObject
, ResolveOperation
* resolveOperation
) 
 617     ASSERT(resolveOperation
); 
 618     ASSERT(resolveOperation
->m_operation 
== ResolveOperation::GetAndReturnGlobalProperty
); 
 619     ASSERT_UNUSED(globalObject
, callFrame
->lexicalGlobalObject() == globalObject
); 
 621     LookupResult fastResult
; 
 622     if (executeResolveOperations(callFrame
, callFrame
->scope(), identifier
, resolveOperation
, fastResult
)) { 
 623         ASSERT(fastResult
.value()); 
 624         ASSERT(!callFrame
->hadException()); 
 625         return fastResult
.value(); 
 628     if (callFrame
->hadException()) 
 631     return throwError(callFrame
, createUndefinedVariableError(callFrame
, identifier
));