X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/93a3786624b2768d89bfa27e46598dc64e2fb70a..refs/heads/master:/runtime/JSScope.h diff --git a/runtime/JSScope.h b/runtime/JSScope.h index 95db8ad..5d0eb4b 100644 --- a/runtime/JSScope.h +++ b/runtime/JSScope.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All Rights Reserved. + * Copyright (C) 2012, 2013, 2014 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,36 +27,144 @@ #define JSScope_h #include "JSObject.h" -#include "ResolveOperation.h" namespace JSC { class ScopeChainIterator; +class WatchpointSet; + +enum ResolveMode { + ThrowIfNotFound, + DoNotThrowIfNotFound +}; + +enum ResolveType { + // Lexical scope guaranteed a certain type of variable access. + GlobalProperty, + GlobalVar, + ClosureVar, + LocalClosureVar, + + // Ditto, but at least one intervening scope used non-strict eval, which + // can inject an intercepting var delcaration at runtime. + GlobalPropertyWithVarInjectionChecks, + GlobalVarWithVarInjectionChecks, + ClosureVarWithVarInjectionChecks, + + // Lexical scope didn't prove anything -- probably because of a 'with' scope. + Dynamic +}; + +const char* resolveModeName(ResolveMode mode); +const char* resolveTypeName(ResolveType type); + +inline ResolveType makeType(ResolveType type, bool needsVarInjectionChecks) +{ + if (!needsVarInjectionChecks) + return type; + + switch (type) { + case GlobalProperty: + return GlobalPropertyWithVarInjectionChecks; + case GlobalVar: + return GlobalVarWithVarInjectionChecks; + case ClosureVar: + case LocalClosureVar: + return ClosureVarWithVarInjectionChecks; + case GlobalPropertyWithVarInjectionChecks: + case GlobalVarWithVarInjectionChecks: + case ClosureVarWithVarInjectionChecks: + case Dynamic: + return type; + } + + RELEASE_ASSERT_NOT_REACHED(); + return type; +} + +inline bool needsVarInjectionChecks(ResolveType type) +{ + switch (type) { + case GlobalProperty: + case GlobalVar: + case ClosureVar: + case LocalClosureVar: + return false; + case GlobalPropertyWithVarInjectionChecks: + case GlobalVarWithVarInjectionChecks: + case ClosureVarWithVarInjectionChecks: + case Dynamic: + return true; + default: + RELEASE_ASSERT_NOT_REACHED(); + return true; + } +} + +struct ResolveOp { + ResolveOp(ResolveType type, size_t depth, Structure* structure, JSLexicalEnvironment* lexicalEnvironment, WatchpointSet* watchpointSet, uintptr_t operand) + : type(type) + , depth(depth) + , structure(structure) + , lexicalEnvironment(lexicalEnvironment) + , watchpointSet(watchpointSet) + , operand(operand) + { + } + + ResolveType type; + size_t depth; + Structure* structure; + JSLexicalEnvironment* lexicalEnvironment; + WatchpointSet* watchpointSet; + uintptr_t operand; +}; + +class ResolveModeAndType { + typedef unsigned Operand; +public: + static const size_t shift = sizeof(Operand) * 8 / 2; + static const unsigned mask = (1 << shift) - 1; + + ResolveModeAndType(ResolveMode resolveMode, ResolveType resolveType) + : m_operand((resolveMode << shift) | resolveType) + { + } + + explicit ResolveModeAndType(unsigned operand) + : m_operand(operand) + { + } + + ResolveMode mode() { return static_cast(m_operand >> shift); } + ResolveType type() { return static_cast(m_operand & mask); } + unsigned operand() { return m_operand; } + +private: + Operand m_operand; +}; + +enum GetOrPut { Get, Put }; class JSScope : public JSNonFinalObject { public: typedef JSNonFinalObject Base; + static const unsigned StructureFlags = Base::StructureFlags; friend class LLIntOffsetsExtractor; static size_t offsetOfNext(); - JS_EXPORT_PRIVATE static JSObject* objectAtScope(JSScope*); + static JSObject* objectAtScope(JSScope*); - static JSValue resolve(CallFrame*, const Identifier&, ResolveOperations*); - static JSValue resolveBase(CallFrame*, const Identifier&, bool isStrict, ResolveOperations*, PutToBaseOperation*); - static JSValue resolveWithBase(CallFrame*, const Identifier&, Register* base, ResolveOperations*, PutToBaseOperation*); - static JSValue resolveWithThis(CallFrame*, const Identifier&, Register* base, ResolveOperations*); - static JSValue resolveGlobal(CallFrame*, const Identifier&, JSGlobalObject*, ResolveOperation*); - static void resolvePut(CallFrame*, JSValue base, const Identifier&, JSValue, PutToBaseOperation*); + static JSValue resolve(ExecState*, JSScope*, const Identifier&); + static ResolveOp abstractResolve(ExecState*, bool hasTopActivation, JSScope*, const Identifier&, GetOrPut, ResolveType); static void visitChildren(JSCell*, SlotVisitor&); - bool isDynamicScope(bool& requiresDynamicChecks) const; - ScopeChainIterator begin(); ScopeChainIterator end(); JSScope* next(); - int localDepth(); + int depth(); JSGlobalObject* globalObject(); VM* vm(); @@ -64,20 +172,9 @@ public: protected: JSScope(VM&, Structure*, JSScope* next); - static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; private: WriteBarrier m_next; - enum ReturnValues { - ReturnValue = 1, - ReturnBase = 2, - ReturnThis = 4, - ReturnBaseAndValue = ReturnValue | ReturnBase, - ReturnThisAndValue = ReturnValue | ReturnThis, - }; - enum LookupMode { UnknownResolve, KnownResolve }; - template static JSObject* resolveContainingScopeInternal(CallFrame*, const Identifier&, PropertySlot&, ResolveOperations*, PutToBaseOperation*, bool isStrict); - template static JSObject* resolveContainingScope(CallFrame*, const Identifier&, PropertySlot&, ResolveOperations*, PutToBaseOperation*, bool isStrict); }; inline JSScope::JSScope(VM& vm, Structure* structure, JSScope* next) @@ -95,6 +192,7 @@ public: JSObject* get() const { return JSScope::objectAtScope(m_node); } JSObject* operator->() const { return JSScope::objectAtScope(m_node); } + JSScope* scope() const { return m_node; } ScopeChainIterator& operator++() { m_node = m_node->next(); return *this; } @@ -129,7 +227,7 @@ inline JSGlobalObject* JSScope::globalObject() inline VM* JSScope::vm() { - return Heap::heap(this)->vm(); + return MarkedBlock::blockFor(this)->vm(); } inline Register& Register::operator=(JSScope* scope) @@ -143,20 +241,9 @@ inline JSScope* Register::scope() const return jsCast(jsValue()); } -inline VM& ExecState::vm() const -{ - ASSERT(scope()->vm()); - return *scope()->vm(); -} - inline JSGlobalObject* ExecState::lexicalGlobalObject() const { - return scope()->globalObject(); -} - -inline JSObject* ExecState::globalThisValue() const -{ - return scope()->globalThis(); + return callee()->globalObject(); } inline size_t JSScope::offsetOfNext()