⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scopes.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
  // which we don't know anything at this point. Thus we must be conservative  // and assume they may invoke eval themselves. Eventually we could capture  // this information in the ScopeInfo and then use it here (by traversing  // the call chain stack, at compile time).  PropagateScopeInfo(is_eval_scope());  // 2) Resolve variables.  Scope* global_scope = NULL;  if (is_global_scope()) global_scope = this;  ResolveVariablesRecursively(global_scope);  // 3) Allocate variables.  AllocateVariablesRecursively();}bool Scope::SupportsEval() const {  return scope_calls_eval_ || inner_scope_calls_eval_;}bool Scope::AllowsLazyCompilation() const {  return !force_eager_compilation_ && HasTrivialOuterContext();}bool Scope::HasTrivialContext() const {  // A function scope has a trivial context if it always is the global  // context. We iteratively scan out the context chain to see if  // there is anything that makes this scope non-trivial; otherwise we  // return true.  for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {    if (scope->is_eval_scope()) return false;    if (scope->scope_inside_with_) return false;    if (scope->num_heap_slots_ > 0) return false;  }  return true;}bool Scope::HasTrivialOuterContext() const {  Scope* outer = outer_scope_;  if (outer == NULL) return true;  // Note that the outer context may be trivial in general, but the current  // scope may be inside a 'with' statement in which case the outer context  // for this scope is not trivial.  return !scope_inside_with_ && outer->HasTrivialContext();}int Scope::ContextChainLength(Scope* scope) {  int n = 0;  for (Scope* s = this; s != scope; s = s->outer_scope_) {    ASSERT(s != NULL);  // scope must be in the scope chain    if (s->num_heap_slots() > 0) n++;  }  return n;}#ifdef DEBUGstatic const char* Header(Scope::Type type) {  switch (type) {    case Scope::EVAL_SCOPE: return "eval";    case Scope::FUNCTION_SCOPE: return "function";    case Scope::GLOBAL_SCOPE: return "global";  }  UNREACHABLE();  return NULL;}static void Indent(int n, const char* str) {  PrintF("%*s%s", n, "", str);}static void PrintName(Handle<String> name) {  SmartPointer<char> s = name->ToCString(DISALLOW_NULLS);  PrintF("%s", *s);}static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) {  if (var->var_uses()->is_used() || var->rewrite() != NULL) {    Indent(indent, Variable::Mode2String(var->mode()));    PrintF(" ");    PrintName(var->name());    PrintF(";  // ");    if (var->rewrite() != NULL) PrintF("%s, ", printer->Print(var->rewrite()));    if (var->is_accessed_from_inner_scope()) PrintF("inner scope access, ");    PrintF("var ");    var->var_uses()->Print();    PrintF(", obj ");    var->obj_uses()->Print();    PrintF("\n");  }}void Scope::Print(int n) {  int n0 = (n > 0 ? n : 0);  int n1 = n0 + 2;  // indentation  // Print header.  Indent(n0, Header(type_));  if (scope_name_->length() > 0) {    PrintF(" ");    PrintName(scope_name_);  }  // Print parameters, if any.  if (is_function_scope()) {    PrintF(" (");    for (int i = 0; i < params_.length(); i++) {      if (i > 0) PrintF(", ");      PrintName(params_[i]->name());    }    PrintF(")");  }  PrintF(" {\n");  // Function name, if any (named function literals, only).  if (function_ != NULL) {    Indent(n1, "// (local) function name: ");    PrintName(function_->name());    PrintF("\n");  }  // Scope info.  if (HasTrivialOuterContext()) {    Indent(n1, "// scope has trivial outer context\n");  }  if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");  if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");  if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");  if (outer_scope_calls_eval_) Indent(n1, "// outer scope calls 'eval'\n");  if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");  if (num_stack_slots_ > 0) { Indent(n1, "// ");  PrintF("%d stack slots\n", num_stack_slots_); }  if (num_heap_slots_ > 0) { Indent(n1, "// ");  PrintF("%d heap slots\n", num_heap_slots_); }  // Print locals.  PrettyPrinter printer;  Indent(n1, "// function var\n");  if (function_ != NULL) {    PrintVar(&printer, n1, function_);  }  Indent(n1, "// temporary vars\n");  for (int i = 0; i < temps_.length(); i++) {    PrintVar(&printer, n1, temps_[i]);  }  Indent(n1, "// local vars\n");  for (LocalsMap::Entry* p = locals_.Start(); p != NULL; p = locals_.Next(p)) {    Variable* var = reinterpret_cast<Variable*>(p->value);    PrintVar(&printer, n1, var);  }  Indent(n1, "// nonlocal vars\n");  for (int i = 0; i < nonlocals_.length(); i++)    PrintVar(&printer, n1, nonlocals_[i]);  // Print inner scopes (disable by providing negative n).  if (n >= 0) {    for (int i = 0; i < inner_scopes_.length(); i++) {      PrintF("\n");      inner_scopes_[i]->Print(n1);    }  }  Indent(n0, "}\n");}#endif  // DEBUGVariable* Scope::NonLocal(Handle<String> name) {  // Space optimization: reuse existing non-local with the same name.  for (int i = 0; i < nonlocals_.length(); i++) {    Variable* var = nonlocals_[i];    if (var->name().is_identical_to(name)) {      ASSERT(var->mode() == Variable::DYNAMIC);      return var;    }  }  // Otherwise create a new new-local and add it to the list.  Variable* var = new Variable(    NULL /* we don't know the scope */,    name, Variable::DYNAMIC, true, false);  nonlocals_.Add(var);  // Allocate it by giving it a dynamic lookup.  var->rewrite_ = new Slot(var, Slot::LOOKUP, -1);  return var;}// Lookup a variable starting with this scope. The result is either// the statically resolved (local!) variable belonging to an outer scope,// or NULL. It may be NULL because a) we couldn't find a variable, or b)// because the variable is just a guess (and may be shadowed by another// variable that is introduced dynamically via an 'eval' call or a 'with'// statement).Variable* Scope::LookupRecursive(Handle<String> name, bool inner_lookup) {  // If we find a variable, but the current scope calls 'eval', the found  // variable may not be the correct one (the 'eval' may introduce a  // property with the same name). In that case, remember that the variable  // found is just a guess.  bool guess = scope_calls_eval_;  // Try to find the variable in this scope.  Variable* var = Lookup(name);  if (var != NULL) {    // We found a variable. If this is not an inner lookup, we are done.    // (Even if there is an 'eval' in this scope which introduces the    // same variable again, the resulting variable remains the same.    // Note that enclosing 'with' statements are handled at the call site.)    if (!inner_lookup)      return var;  } else {    // We did not find a variable locally. Check against the function variable,    // if any. We can do this for all scopes, since the function variable is    // only present - if at all - for function scopes.    //    // This lookup corresponds to a lookup in the "intermediate" scope sitting    // between this scope and the outer scope. (ECMA-262, 3rd., requires that    // the name of named function literal is kept in an intermediate scope    // inbetween this scope and the next outer scope.)    if (function_ != NULL && function_->name().is_identical_to(name)) {      var = function_;    } else if (outer_scope_ != NULL) {      var = outer_scope_->LookupRecursive(name, true /* inner lookup */);      // We may have found a variable in an outer scope. However, if      // the current scope is inside a 'with', the actual variable may      // be a property introduced via the 'with' statement. Then, the      // variable we may have found is just a guess.      if (scope_inside_with_)        guess = true;    }    // If we did not find a variable, we are done.    if (var == NULL)      return NULL;  }  ASSERT(var != NULL);  // If this is a lookup from an inner scope, mark the variable.  if (inner_lookup)    var->is_accessed_from_inner_scope_ = true;  // If the variable we have found is just a guess, invalidate the result.  if (guess)    var = NULL;  return var;}void Scope::ResolveVariable(Scope* global_scope, VariableProxy* proxy) {  ASSERT(global_scope == NULL || global_scope->is_global_scope());  // If the proxy is already resolved there's nothing to do  // (functions and consts may be resolved by the parser).  if (proxy->var() != NULL) return;  // Otherwise, try to resolve the variable.  Variable* var = LookupRecursive(proxy->name(), false);  if (proxy->inside_with()) {    // If we are inside a local 'with' statement, all bets are off    // and we cannot resolve the proxy to a local variable even if    // we found an outer matching variable.    // Note that we must do a lookup anyway, because if we find one,    // we must mark that variable as potentially accessed from this    // inner scope (the property may not be in the 'with' object).    var = NonLocal(proxy->name());  } else {    // We are not inside a local 'with' statement.    if (var == NULL) {      // We did not find the variable. We have a global variable      // if we are in the global scope (we know already that we      // are outside a 'with' statement) or if there is no way      // that the variable might be introduced dynamically (through      // a local or outer eval() call, or an outer 'with' statement),      // or we don't know about the outer scope (because we are      // in an eval scope).      if (!is_global_scope() &&          (is_eval_scope() || outer_scope_calls_eval_ ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -