Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
code->set_optimizable(info->IsOptimizable() &&
- !info->function()->flags()->Contains(kDontOptimize));
+ !info->function()->flags()->Contains(kDontOptimize) &&
+ info->function()->scope()->AllowsLazyRecompilation());
cgen.PopulateDeoptimizationData(code);
cgen.PopulateTypeFeedbackInfo(code);
cgen.PopulateTypeFeedbackCells(code);
}
+bool Scope::AllowsLazyRecompilation() const {
+ return !force_eager_compilation_ &&
+ !TrivialDeclarationScopesBeforeWithScope();
+}
+
+
+bool Scope::TrivialDeclarationScopesBeforeWithScope() const {
+ Scope* outer = outer_scope_;
+ if (outer == NULL) return false;
+ outer = outer->DeclarationScope();
+ while (outer != NULL) {
+ if (outer->is_with_scope()) return true;
+ if (outer->is_declaration_scope() && outer->num_heap_slots() > 0)
+ return false;
+ outer = outer->outer_scope_;
+ }
+ return false;
+}
+
+
int Scope::ContextChainLength(Scope* scope) {
int n = 0;
for (Scope* s = this; s != scope; s = s->outer_scope_) {
bool AllowsLazyCompilation() const;
// True if we can lazily recompile functions with this scope.
- bool allows_lazy_recompilation() const {
- return !force_eager_compilation_;
- }
+ bool AllowsLazyRecompilation() const;
// True if the outer context of this scope is always the global context.
bool HasTrivialOuterContext() const;
+ // True if this scope is inside a with scope and all declaration scopes
+ // between them have empty contexts. Such declaration scopes become
+ // invisible during scope info deserialization.
+ bool TrivialDeclarationScopesBeforeWithScope() const;
+
// The number of contexts between this and scope; zero if this == scope.
int ContextChainLength(Scope* scope);
--- /dev/null
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+a = {};
+
+a.b = 42;
+
+with(a) {
+ a.f = (function f1() {
+ function f2() {
+ return b;
+ };
+ return f2;
+ })();
+}
+
+for(var i = 0; i < 10000; i++) {
+ assertEquals(42, a.f());
+}
+
+with(a) {
+ a.g = (function f1() {
+ function f2() {
+ function f3() {
+ return b;
+ }
+ return f3;
+ };
+ return f2();
+ })();
+}
+
+for(var i = 0; i < 10000; i++) {
+ assertEquals(42, a.g());
+}
+
+function outer() {
+ with(a) {
+ a.h = (function f1() {
+ function f2() {
+ function f3() {
+ return b;
+ }
+ return f3;
+ };
+ return f2();
+ })();
+ }
+};
+
+outer();
+
+for(var i = 0; i < 10000; i++) {
+ assertEquals(42, a.h());
+}