| Index: src/code-stubs-hydrogen.cc
|
| diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
|
| index 3e18138eb2b459bc9b0f56392aae3334d2b643f6..35927f494bd6445eca6f1f303ecd1f455c196514 100644
|
| --- a/src/code-stubs-hydrogen.cc
|
| +++ b/src/code-stubs-hydrogen.cc
|
| @@ -112,6 +112,13 @@ class CodeStubGraphBuilderBase : public HGraphBuilder {
|
| HValue* BuildInternalArrayConstructor(ElementsKind kind,
|
| ArgumentClass argument_class);
|
|
|
| + void BuildInstallOptimizedCode(HValue* js_function, HValue* native_context,
|
| + HValue* code_object);
|
| + void BuildInstallCode(HValue* js_function, HValue* shared_info);
|
| + void BuildInstallFromOptimizedCodeMap(HValue* js_function,
|
| + HValue* shared_info,
|
| + HValue* native_context);
|
| +
|
| private:
|
| HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder);
|
| HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder,
|
| @@ -904,4 +911,194 @@ Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() {
|
| }
|
|
|
|
|
| +void CodeStubGraphBuilderBase::BuildInstallOptimizedCode(
|
| + HValue* js_function,
|
| + HValue* native_context,
|
| + HValue* code_object) {
|
| + Counters* counters = isolate()->counters();
|
| + AddIncrementCounter(counters->fast_new_closure_install_optimized(),
|
| + context());
|
| +
|
| + // TODO(fschneider): Idea: store proper code pointers in the optimized code
|
| + // map and either unmangle them on marking or do nothing as the whole map is
|
| + // discarded on major GC anyway.
|
| + Add<HStoreCodeEntry>(js_function, code_object);
|
| +
|
| + // Now link a function into a list of optimized functions.
|
| + HValue* optimized_functions_list = Add<HLoadNamedField>(native_context,
|
| + HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST));
|
| + Add<HStoreNamedField>(js_function,
|
| + HObjectAccess::ForNextFunctionLinkPointer(),
|
| + optimized_functions_list);
|
| +
|
| + // This store is the only one that should have a write barrier.
|
| + Add<HStoreNamedField>(native_context,
|
| + HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST),
|
| + js_function);
|
| +}
|
| +
|
| +
|
| +void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function,
|
| + HValue* shared_info) {
|
| + Add<HStoreNamedField>(js_function,
|
| + HObjectAccess::ForNextFunctionLinkPointer(),
|
| + graph()->GetConstantUndefined());
|
| + HValue* code_object = Add<HLoadNamedField>(shared_info,
|
| + HObjectAccess::ForCodeOffset());
|
| + Add<HStoreCodeEntry>(js_function, code_object);
|
| +}
|
| +
|
| +
|
| +void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
|
| + HValue* js_function,
|
| + HValue* shared_info,
|
| + HValue* native_context) {
|
| + Counters* counters = isolate()->counters();
|
| + IfBuilder is_optimized(this);
|
| + HInstruction* optimized_map = Add<HLoadNamedField>(shared_info,
|
| + HObjectAccess::ForOptimizedCodeMap());
|
| + HValue* null_constant = Add<HConstant>(0);
|
| + is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant);
|
| + is_optimized.Then();
|
| + {
|
| + BuildInstallCode(js_function, shared_info);
|
| + }
|
| + is_optimized.Else();
|
| + {
|
| + AddIncrementCounter(counters->fast_new_closure_try_optimized(), context());
|
| + // optimized_map points to fixed array of 3-element entries
|
| + // (native context, optimized code, literals).
|
| + // Map must never be empty, so check the first elements.
|
| + Label install_optimized;
|
| + HValue* first_context_slot = Add<HLoadNamedField>(optimized_map,
|
| + HObjectAccess::ForFirstContextSlot());
|
| + IfBuilder already_in(this);
|
| + already_in.If<HCompareObjectEqAndBranch>(native_context,
|
| + first_context_slot);
|
| + already_in.Then();
|
| + {
|
| + HValue* code_object = Add<HLoadNamedField>(optimized_map,
|
| + HObjectAccess::ForFirstCodeSlot());
|
| + BuildInstallOptimizedCode(js_function, native_context, code_object);
|
| + }
|
| + already_in.Else();
|
| + {
|
| + HValue* shared_function_entry_length =
|
| + Add<HConstant>(SharedFunctionInfo::kEntryLength);
|
| + LoopBuilder loop_builder(this,
|
| + context(),
|
| + LoopBuilder::kPostDecrement,
|
| + shared_function_entry_length);
|
| + HValue* array_length = Add<HLoadNamedField>(optimized_map,
|
| + HObjectAccess::ForFixedArrayLength());
|
| + HValue* key = loop_builder.BeginBody(array_length,
|
| + graph()->GetConstant0(),
|
| + Token::GT);
|
| + {
|
| + // Iterate through the rest of map backwards.
|
| + // Do not double check first entry.
|
| + HValue* second_entry_index =
|
| + Add<HConstant>(SharedFunctionInfo::kSecondEntryIndex);
|
| + IfBuilder restore_check(this);
|
| + restore_check.If<HCompareNumericAndBranch>(key, second_entry_index,
|
| + Token::EQ);
|
| + restore_check.Then();
|
| + {
|
| + // Store the unoptimized code
|
| + BuildInstallCode(js_function, shared_info);
|
| + loop_builder.Break();
|
| + }
|
| + restore_check.Else();
|
| + {
|
| + HValue* keyed_minus = AddInstruction(HSub::New(zone(), context(), key,
|
| + shared_function_entry_length));
|
| + HInstruction* keyed_lookup = Add<HLoadKeyed>(optimized_map,
|
| + keyed_minus, static_cast<HValue*>(NULL), FAST_ELEMENTS);
|
| + IfBuilder done_check(this);
|
| + done_check.If<HCompareObjectEqAndBranch>(native_context,
|
| + keyed_lookup);
|
| + done_check.Then();
|
| + {
|
| + // Hit: fetch the optimized code.
|
| + HValue* keyed_plus = AddInstruction(HAdd::New(zone(), context(),
|
| + keyed_minus, graph()->GetConstant1()));
|
| + HValue* code_object = Add<HLoadKeyed>(optimized_map,
|
| + keyed_plus, static_cast<HValue*>(NULL), FAST_ELEMENTS);
|
| + BuildInstallOptimizedCode(js_function, native_context, code_object);
|
| +
|
| + // Fall out of the loop
|
| + loop_builder.Break();
|
| + }
|
| + done_check.Else();
|
| + done_check.End();
|
| + }
|
| + restore_check.End();
|
| + }
|
| + loop_builder.EndBody();
|
| + }
|
| + already_in.End();
|
| + }
|
| + is_optimized.End();
|
| +}
|
| +
|
| +
|
| +template<>
|
| +HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() {
|
| + Counters* counters = isolate()->counters();
|
| + Factory* factory = isolate()->factory();
|
| + HInstruction* empty_fixed_array =
|
| + Add<HConstant>(factory->empty_fixed_array());
|
| + HValue* shared_info = GetParameter(0);
|
| +
|
| + // Create a new closure from the given function info in new space
|
| + HValue* size = Add<HConstant>(JSFunction::kSize);
|
| + HInstruction* js_function = Add<HAllocate>(size, HType::JSObject(),
|
| + NOT_TENURED, JS_FUNCTION_TYPE);
|
| + AddIncrementCounter(counters->fast_new_closure_total(), context());
|
| +
|
| + int map_index = Context::FunctionMapIndex(casted_stub()->language_mode(),
|
| + casted_stub()->is_generator());
|
| +
|
| + // Compute the function map in the current native context and set that
|
| + // as the map of the allocated object.
|
| + HInstruction* native_context = BuildGetNativeContext();
|
| + HInstruction* map_slot_value = Add<HLoadNamedField>(native_context,
|
| + HObjectAccess::ForContextSlot(map_index));
|
| + Add<HStoreNamedField>(js_function, HObjectAccess::ForMap(), map_slot_value);
|
| +
|
| + // Initialize the rest of the function.
|
| + Add<HStoreNamedField>(js_function, HObjectAccess::ForPropertiesPointer(),
|
| + empty_fixed_array);
|
| + Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(),
|
| + empty_fixed_array);
|
| + Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(),
|
| + empty_fixed_array);
|
| + Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(),
|
| + graph()->GetConstantHole());
|
| + Add<HStoreNamedField>(js_function,
|
| + HObjectAccess::ForSharedFunctionInfoPointer(),
|
| + shared_info);
|
| + Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(),
|
| + shared_info);
|
| + Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(),
|
| + context());
|
| +
|
| + // Initialize the code pointer in the function to be the one
|
| + // found in the shared function info object.
|
| + // But first check if there is an optimized version for our context.
|
| + if (FLAG_cache_optimized_code) {
|
| + BuildInstallFromOptimizedCodeMap(js_function, shared_info, native_context);
|
| + } else {
|
| + BuildInstallCode(js_function, shared_info);
|
| + }
|
| +
|
| + return js_function;
|
| +}
|
| +
|
| +
|
| +Handle<Code> FastNewClosureStub::GenerateCode() {
|
| + return DoGenerateCode(this);
|
| +}
|
| +
|
| +
|
| } } // namespace v8::internal
|
|
|