Handle<JSFunction> function = info->closure();
ASSERT(!function.is_null());
Handle<Context> global_context(function->context()->global_context());
- int index = function->shared()->SearchOptimizedCodeMap(*global_context);
+ int index = shared->SearchOptimizedCodeMap(*global_context);
if (index > 0) {
if (FLAG_trace_opt) {
- PrintF(" [Found optimized code for");
+ PrintF("[found optimized code for: ");
function->PrintName();
- PrintF("\n");
+ PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(*function));
}
- Code* code = Code::cast(
- FixedArray::cast(shared->optimized_code_map())->get(index));
- ASSERT(code != NULL);
- function->ReplaceCode(code);
+ // Caching of optimized code enabled and optimized code found.
+ shared->InstallFromOptimizedCodeMap(*function, index);
return true;
}
}
if (FLAG_cache_optimized_code &&
code->kind() == Code::OPTIMIZED_FUNCTION) {
Handle<SharedFunctionInfo> shared(function->shared());
+ Handle<FixedArray> literals(function->literals());
Handle<Context> global_context(function->context()->global_context());
-
- // Create literals array that will be shared for this global context.
- int number_of_literals = shared->num_literals();
- Handle<FixedArray> literals =
- isolate->factory()->NewFixedArray(number_of_literals);
- if (number_of_literals > 0) {
- // Store the object, regexp and array functions in the literals
- // array prefix. These functions will be used when creating
- // object, regexp and array literals in this function.
- literals->set(JSFunction::kLiteralGlobalContextIndex,
- function->context()->global_context());
- }
-
SharedFunctionInfo::AddToOptimizedCodeMap(
shared, global_context, code, literals);
}
result->set_context(*context);
- int index = FLAG_cache_optimized_code
- ? function_info->SearchOptimizedCodeMap(context->global_context())
- : -1;
- if (!function_info->bound()) {
- if (index > 0) {
- FixedArray* code_map =
- FixedArray::cast(function_info->optimized_code_map());
- FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1));
- ASSERT(cached_literals != NULL);
- ASSERT(function_info->num_literals() == 0 ||
- (code_map->get(index - 1) ==
- cached_literals->get(JSFunction::kLiteralGlobalContextIndex)));
- result->set_literals(cached_literals);
- } else {
- int number_of_literals = function_info->num_literals();
- Handle<FixedArray> literals =
- NewFixedArray(number_of_literals, pretenure);
- if (number_of_literals > 0) {
- // Store the object, regexp and array functions in the literals
- // array prefix. These functions will be used when creating
- // object, regexp and array literals in this function.
- literals->set(JSFunction::kLiteralGlobalContextIndex,
- context->global_context());
- }
- result->set_literals(*literals);
+ int index = function_info->SearchOptimizedCodeMap(context->global_context());
+ if (!function_info->bound() && index < 0) {
+ int number_of_literals = function_info->num_literals();
+ Handle<FixedArray> literals = NewFixedArray(number_of_literals, pretenure);
+ if (number_of_literals > 0) {
+ // Store the global context in the literals array prefix. This
+ // context will be used when creating object, regexp and array
+ // literals in this function.
+ literals->set(JSFunction::kLiteralGlobalContextIndex,
+ context->global_context());
}
+ result->set_literals(*literals);
}
if (index > 0) {
// Caching of optimized code enabled and optimized code found.
- Code* code = Code::cast(
- FixedArray::cast(function_info->optimized_code_map())->get(index));
- ASSERT(code != NULL);
- result->ReplaceCode(code);
+ function_info->InstallFromOptimizedCodeMap(*result, index);
return result;
}
DEFINE_bool(lookup_sample_by_shared, true,
"when picking a function to optimize, watch for shared function "
"info, not JSFunction itself")
-DEFINE_bool(cache_optimized_code, false,
+DEFINE_bool(cache_optimized_code, true,
"cache optimized code for closures")
DEFINE_bool(inline_construct, true, "inline constructor calls")
DEFINE_bool(inline_arguments, true, "inline functions with arguments object")
}
+void SharedFunctionInfo::InstallFromOptimizedCodeMap(JSFunction* function,
+ int index) {
+ ASSERT(index > 0);
+ ASSERT(optimized_code_map()->IsFixedArray());
+ FixedArray* code_map = FixedArray::cast(optimized_code_map());
+ if (!bound()) {
+ FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1));
+ ASSERT(cached_literals != NULL);
+ function->set_literals(cached_literals);
+ }
+ Code* code = Code::cast(code_map->get(index));
+ ASSERT(code != NULL);
+ ASSERT(function->context()->global_context() == code_map->get(index - 1));
+ function->ReplaceCode(code);
+}
+
+
bool JSFunction::CompileLazy(Handle<JSFunction> function,
ClearExceptionFlag flag) {
bool result = true;
int SharedFunctionInfo::SearchOptimizedCodeMap(Context* global_context) {
ASSERT(global_context->IsGlobalContext());
+ if (!FLAG_cache_optimized_code) return -1;
Object* value = optimized_code_map();
if (!value->IsSmi()) {
FixedArray* optimized_code_map = FixedArray::cast(value);
// Returns -1 when no matching entry is found.
int SearchOptimizedCodeMap(Context* global_context);
+ // Installs optimized code from the code map on the given closure. The
+ // index has to be consistent with a search result as defined above.
+ void InstallFromOptimizedCodeMap(JSFunction* function, int index);
+
// Clear optimized code map.
void ClearOptimizedCodeMap();
// Check if boilerplate exists. If not, create it first.
Handle<Object> boilerplate(literals->get(literals_index), isolate);
if (*boilerplate == isolate->heap()->undefined_value()) {
+ ASSERT(*elements != isolate->heap()->empty_fixed_array());
boilerplate =
Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
if (boilerplate.is_null()) return Failure::Exception();
--- /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.
+
+// Flags: --allow-natives-syntax --cache-optimized-code
+
+function bozo() {};
+function MakeClosure() {
+ return function f(use_literals) {
+ if (use_literals) {
+ return [1,2,3,3,4,5,6,7,8,9,bozo];
+ } else {
+ return 0;
+ }
+ }
+}
+
+// Create two closures that share the same literal boilerplates.
+var closure1 = MakeClosure();
+var closure2 = MakeClosure();
+var expected = [1,2,3,3,4,5,6,7,8,9,bozo];
+
+// Make sure we generate optimized code for the first closure after
+// warming it up properly so that the literals boilerplate is generated
+// and the optimized code uses CreateArrayLiteralShallow runtime call.
+assertEquals(0, closure1(false));
+assertEquals(expected, closure1(true));
+%OptimizeFunctionOnNextCall(closure1);
+assertEquals(expected, closure1(true));
+
+// Optimize the second closure, which should reuse the optimized code
+// from the first closure with the same literal boilerplates.
+assertEquals(0, closure2(false));
+%OptimizeFunctionOnNextCall(closure2);
+assertEquals(expected, closure2(true));