Revision: 16356
Author: [email protected]
Date: Tue Aug 27 11:55:08 2013 UTC
Log: Convert FastNewClosureStub into hydrogen.
BUG=
[email protected]
Review URL: https://codereview.chromium.org/22562002
http://code.google.com/p/v8/source/detail?r=16356
Modified:
/branches/bleeding_edge/src/arm/code-stubs-arm.cc
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/arm/lithium-arm.cc
/branches/bleeding_edge/src/arm/lithium-arm.h
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/code-stubs-hydrogen.cc
/branches/bleeding_edge/src/code-stubs.cc
/branches/bleeding_edge/src/code-stubs.h
/branches/bleeding_edge/src/hydrogen-instructions.cc
/branches/bleeding_edge/src/hydrogen-instructions.h
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/hydrogen.h
/branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-ia32.h
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
/branches/bleeding_edge/src/x64/code-stubs-x64.cc
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
/branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
/branches/bleeding_edge/src/x64/lithium-x64.cc
/branches/bleeding_edge/src/x64/lithium-x64.h
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Mon Aug 26 12:24:03
2013 UTC
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Tue Aug 27 11:55:08
2013 UTC
@@ -36,6 +36,17 @@
namespace v8 {
namespace internal {
+
+
+void FastNewClosureStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { r2 };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry;
+}
void ToNumberStub::InitializeInterfaceDescriptor(
@@ -307,134 +318,6 @@
__ Ret();
}
-
-
-void FastNewClosureStub::Generate(MacroAssembler* masm) {
- // Create a new closure from the given function info in new
- // space. Set the context to the current context in cp.
- Counters* counters = masm->isolate()->counters();
-
- Label gc;
-
- // Pop the function info from the stack.
- __ pop(r3);
-
- // Attempt to allocate new JSFunction in new space.
- __ Allocate(JSFunction::kSize, r0, r1, r2, &gc, TAG_OBJECT);
-
- __ IncrementCounter(counters->fast_new_closure_total(), 1, r6, r7);
-
- int map_index = Context::FunctionMapIndex(language_mode_, is_generator_);
-
- // Compute the function map in the current native context and set that
- // as the map of the allocated object.
- __ ldr(r2, MemOperand(cp,
Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
- __ ldr(r2, FieldMemOperand(r2, GlobalObject::kNativeContextOffset));
- __ ldr(r5, MemOperand(r2, Context::SlotOffset(map_index)));
- __ str(r5, FieldMemOperand(r0, HeapObject::kMapOffset));
-
- // Initialize the rest of the function. We don't have to update the
- // write barrier because the allocated object is in new space.
- __ LoadRoot(r1, Heap::kEmptyFixedArrayRootIndex);
- __ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
- __ str(r1, FieldMemOperand(r0, JSObject::kPropertiesOffset));
- __ str(r1, FieldMemOperand(r0, JSObject::kElementsOffset));
- __ str(r5, FieldMemOperand(r0,
JSFunction::kPrototypeOrInitialMapOffset));
- __ str(r3, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
- __ str(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
- __ str(r1, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
-
- // 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.
- Label check_optimized;
- Label install_unoptimized;
- if (FLAG_cache_optimized_code) {
- __ ldr(r1,
- FieldMemOperand(r3,
SharedFunctionInfo::kOptimizedCodeMapOffset));
- __ tst(r1, r1);
- __ b(ne, &check_optimized);
- }
- __ bind(&install_unoptimized);
- __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
- __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset));
- __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
- __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
- __ str(r3, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
-
- // Return result. The argument function info has been popped already.
- __ Ret();
-
- __ bind(&check_optimized);
-
- __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1, r6,
r7);
-
- // r2 holds native context, r1 points to fixed array of 3-element entries
- // (native context, optimized code, literals).
- // The optimized code map must never be empty, so check the first
elements.
- Label install_optimized;
- // Speculatively move code object into r4.
- __ ldr(r4, FieldMemOperand(r1, SharedFunctionInfo::kFirstCodeSlot));
- __ ldr(r5, FieldMemOperand(r1, SharedFunctionInfo::kFirstContextSlot));
- __ cmp(r2, r5);
- __ b(eq, &install_optimized);
-
- // Iterate through the rest of map backwards. r4 holds an index as a
Smi.
- Label loop;
- __ ldr(r4, FieldMemOperand(r1, FixedArray::kLengthOffset));
- __ bind(&loop);
- // Do not double check first entry.
- __ cmp(r4, Operand(Smi::FromInt(SharedFunctionInfo::kSecondEntryIndex)));
- __ b(eq, &install_unoptimized);
- __ sub(r4, r4, Operand(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
- __ add(r5, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
- __ add(r5, r5, Operand::PointerOffsetFromSmiKey(r4));
- __ ldr(r5, MemOperand(r5));
- __ cmp(r2, r5);
- __ b(ne, &loop);
- // Hit: fetch the optimized code.
- __ add(r5, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
- __ add(r5, r5, Operand::PointerOffsetFromSmiKey(r4));
- __ add(r5, r5, Operand(kPointerSize));
- __ ldr(r4, MemOperand(r5));
-
- __ bind(&install_optimized);
- __ IncrementCounter(counters->fast_new_closure_install_optimized(),
- 1, r6, r7);
-
- // TODO(fschneider): Idea: store proper code pointers in the map and
either
- // unmangle them on marking or do nothing as the whole map is discarded
on
- // major GC anyway.
- __ add(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag));
- __ str(r4, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
-
- // Now link a function into a list of optimized functions.
- __ ldr(r4, ContextOperand(r2, Context::OPTIMIZED_FUNCTIONS_LIST));
-
- __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset));
- // No need for write barrier as JSFunction (eax) is in the new space.
-
- __ str(r0, ContextOperand(r2, Context::OPTIMIZED_FUNCTIONS_LIST));
- // Store JSFunction (eax) into edx before issuing write barrier as
- // it clobbers all the registers passed.
- __ mov(r4, r0);
- __ RecordWriteContextSlot(
- r2,
- Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST),
- r4,
- r1,
- kLRHasNotBeenSaved,
- kDontSaveFPRegs);
-
- // Return result. The argument function info has been popped already.
- __ Ret();
-
- // Create a new closure through the slower runtime call.
- __ bind(&gc);
- __ LoadRoot(r4, Heap::kFalseValueRootIndex);
- __ Push(cp, r3, r4);
- __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
-}
void FastNewContextStub::Generate(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Aug 23 11:31:18
2013 UTC
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Tue Aug 27 11:55:08
2013 UTC
@@ -1330,8 +1330,7 @@
scope()->is_function_scope() &&
info->num_literals() == 0) {
FastNewClosureStub stub(info->language_mode(), info->is_generator());
- __ mov(r0, Operand(info));
- __ push(r0);
+ __ mov(r2, Operand(info));
__ CallStub(&stub);
} else {
__ mov(r0, Operand(info));
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Mon Aug 26 17:30:41 2013
UTC
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc Tue Aug 27 11:55:08 2013
UTC
@@ -258,6 +258,14 @@
*hydrogen()->type_literal()->ToCString(),
true_block_id(), false_block_id());
}
+
+
+void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
+ stream->Add(" = ");
+ function()->PrintTo(stream);
+ stream->Add(".code_entry = ");
+ code_object()->PrintTo(stream);
+}
void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
@@ -1077,6 +1085,14 @@
LOperand* argument = Use(instr->argument());
return new(zone()) LPushArgument(argument);
}
+
+
+LInstruction* LChunkBuilder::DoStoreCodeEntry(
+ HStoreCodeEntry* store_code_entry) {
+ LOperand* function = UseRegister(store_code_entry->function());
+ LOperand* code_object = UseTempRegister(store_code_entry->code_object());
+ return new(zone()) LStoreCodeEntry(function, code_object);
+}
LInstruction* LChunkBuilder::DoInnerAllocatedObject(
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h Mon Aug 26 12:24:03 2013
UTC
+++ /branches/bleeding_edge/src/arm/lithium-arm.h Tue Aug 27 11:55:08 2013
UTC
@@ -162,6 +162,7 @@
V(SmiTag) \
V(SmiUntag) \
V(StackCheck) \
+ V(StoreCodeEntry) \
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
@@ -1753,7 +1754,24 @@
};
-class LInnerAllocatedObject V8_FINAL : public LTemplateInstruction<1, 1,
0> {
+class LStoreCodeEntry V8_FINAL: public LTemplateInstruction<0, 1, 1> {
+ public:
+ LStoreCodeEntry(LOperand* function, LOperand* code_object) {
+ inputs_[0] = function;
+ temps_[0] = code_object;
+ }
+
+ LOperand* function() { return inputs_[0]; }
+ LOperand* code_object() { return temps_[0]; }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
+ DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
+};
+
+
+class LInnerAllocatedObject V8_FINAL: public LTemplateInstruction<1, 1, 0>
{
public:
explicit LInnerAllocatedObject(LOperand* base_object) {
inputs_[0] = base_object;
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Aug 26
12:24:03 2013 UTC
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Aug 27
11:55:08 2013 UTC
@@ -4144,6 +4144,15 @@
void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
CallRuntime(instr->function(), instr->arity(), instr);
}
+
+
+void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
+ Register function = ToRegister(instr->function());
+ Register code_object = ToRegister(instr->code_object());
+ __ add(code_object, code_object, Operand(Code::kHeaderSize -
kHeapObjectTag));
+ __ str(code_object,
+ FieldMemOperand(function, JSFunction::kCodeEntryOffset));
+}
void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
@@ -5417,8 +5426,7 @@
if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(instr->hydrogen()->language_mode(),
instr->hydrogen()->is_generator());
- __ mov(r1, Operand(instr->hydrogen()->shared_info()));
- __ push(r1);
+ __ mov(r2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
} else {
__ mov(r2, Operand(instr->hydrogen()->shared_info()));
=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Mon Aug 26 12:28:08
2013 UTC
+++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue Aug 27 11:55:08
2013 UTC
@@ -112,6 +112,13 @@
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,
@@ -902,6 +909,196 @@
Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() {
return DoGenerateCode(this);
}
+
+
+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
=======================================
--- /branches/bleeding_edge/src/code-stubs.cc Mon Aug 19 22:12:46 2013 UTC
+++ /branches/bleeding_edge/src/code-stubs.cc Tue Aug 27 11:55:08 2013 UTC
@@ -757,6 +757,12 @@
ArrayNArgumentsConstructorStub stub3(GetInitialFastElementsKind());
InstallDescriptor(isolate, &stub3);
}
+
+
+void FastNewClosureStub::InstallDescriptors(Isolate* isolate) {
+ FastNewClosureStub stub(STRICT_MODE, false);
+ InstallDescriptor(isolate, &stub);
+}
ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
=======================================
--- /branches/bleeding_edge/src/code-stubs.h Mon Aug 26 12:24:03 2013 UTC
+++ /branches/bleeding_edge/src/code-stubs.h Tue Aug 27 11:55:08 2013 UTC
@@ -489,20 +489,29 @@
};
-class FastNewClosureStub : public PlatformCodeStub {
+class FastNewClosureStub : public HydrogenCodeStub {
public:
explicit FastNewClosureStub(LanguageMode language_mode, bool
is_generator)
: language_mode_(language_mode),
is_generator_(is_generator) { }
- void Generate(MacroAssembler* masm);
+ virtual Handle<Code> GenerateCode();
+
+ virtual void InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor);
+
+ static void InstallDescriptors(Isolate* isolate);
+
+ LanguageMode language_mode() const { return language_mode_; }
+ bool is_generator() const { return is_generator_; }
private:
class StrictModeBits: public BitField<bool, 0, 1> {};
class IsGeneratorBits: public BitField<bool, 1, 1> {};
Major MajorKey() { return FastNewClosure; }
- int MinorKey() {
+ int NotMissMinorKey() {
return StrictModeBits::encode(language_mode_ != CLASSIC_MODE) |
IsGeneratorBits::encode(is_generator_);
}
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Tue Aug 27
11:51:03 2013 UTC
+++ /branches/bleeding_edge/src/hydrogen-instructions.cc Tue Aug 27
11:55:08 2013 UTC
@@ -4043,6 +4043,15 @@
}
return HObjectAccess(portion, offset, representation);
}
+
+
+HObjectAccess HObjectAccess::ForContextSlot(int index) {
+ ASSERT(index >= 0);
+ Portion portion = kInobject;
+ int offset = Context::kHeaderSize + index * kPointerSize;
+ ASSERT_EQ(offset, Context::SlotOffset(index) + kHeapObjectTag);
+ return HObjectAccess(portion, offset, Representation::Tagged());
+}
HObjectAccess HObjectAccess::ForJSArrayOffset(int offset) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Tue Aug 27 11:51:03
2013 UTC
+++ /branches/bleeding_edge/src/hydrogen-instructions.h Tue Aug 27 11:55:08
2013 UTC
@@ -164,6 +164,7 @@
V(Shr) \
V(Simulate) \
V(StackCheck) \
+ V(StoreCodeEntry) \
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
@@ -5200,7 +5201,33 @@
};
-class HInnerAllocatedObject V8_FINAL : public HTemplateInstruction<1> {
+class HStoreCodeEntry V8_FINAL: public HTemplateInstruction<2> {
+ public:
+ static HStoreCodeEntry* New(Zone* zone,
+ HValue* context,
+ HValue* function,
+ HValue* code) {
+ return new(zone) HStoreCodeEntry(function, code);
+ }
+
+ virtual Representation RequiredInputRepresentation(int index) {
+ return Representation::Tagged();
+ }
+
+ HValue* function() { return OperandAt(0); }
+ HValue* code_object() { return OperandAt(1); }
+
+ DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
+
+ private:
+ HStoreCodeEntry(HValue* function, HValue* code) {
+ SetOperandAt(0, function);
+ SetOperandAt(1, code);
+ }
+};
+
+
+class HInnerAllocatedObject V8_FINAL: public HTemplateInstruction<1> {
public:
static HInnerAllocatedObject* New(Zone* zone,
HValue* context,
@@ -5509,6 +5536,14 @@
return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
}
+ static HObjectAccess ForLiteralsPointer() {
+ return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
+ }
+
+ static HObjectAccess ForNextFunctionLinkPointer() {
+ return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
+ }
+
static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
return HObjectAccess(
kArrayLengths,
@@ -5552,6 +5587,35 @@
static HObjectAccess ForPrototypeOrInitialMap() {
return HObjectAccess(kInobject,
JSFunction::kPrototypeOrInitialMapOffset);
}
+
+ static HObjectAccess ForSharedFunctionInfoPointer() {
+ return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
+ }
+
+ static HObjectAccess ForCodeEntryPointer() {
+ return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
+ }
+
+ static HObjectAccess ForCodeOffset() {
+ return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
+ }
+
+ static HObjectAccess ForFirstCodeSlot() {
+ return HObjectAccess(kInobject, SharedFunctionInfo::kFirstCodeSlot);
+ }
+
+ static HObjectAccess ForFirstContextSlot() {
+ return HObjectAccess(kInobject, SharedFunctionInfo::kFirstContextSlot);
+ }
+
+ static HObjectAccess ForOptimizedCodeMap() {
+ return HObjectAccess(kInobject,
+ SharedFunctionInfo::kOptimizedCodeMapOffset);
+ }
+
+ static HObjectAccess ForFunctionContextPointer() {
+ return HObjectAccess(kInobject, JSFunction::kContextOffset);
+ }
static HObjectAccess ForMap() {
return HObjectAccess(kMaps, JSObject::kMapOffset);
@@ -5583,6 +5647,8 @@
// Create an access to an in-object property in a JSArray.
static HObjectAccess ForJSArrayOffset(int offset);
+ static HObjectAccess ForContextSlot(int index);
+
// Create an access to the backing store of an object.
static HObjectAccess ForBackingStoreOffset(int offset,
Representation representation = Representation::Tagged());
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Tue Aug 27 11:44:45 2013 UTC
+++ /branches/bleeding_edge/src/hydrogen.cc Tue Aug 27 11:55:08 2013 UTC
@@ -828,7 +828,6 @@
ASSERT(!captured_);
ASSERT(!finished_);
last_true_block_ = builder_->current_block();
- ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished());
builder_->set_current_block(first_false_block_);
did_else_ = true;
}
@@ -864,9 +863,11 @@
if (!did_else_) {
last_true_block_ = builder_->current_block();
}
- if (first_true_block_ == NULL) {
+ if (last_true_block_ == NULL || last_true_block_->IsFinished()) {
+ ASSERT(did_else_);
// Return on true. Nothing to do, just continue the false block.
- } else if (first_false_block_ == NULL) {
+ } else if (first_false_block_ == NULL ||
+ (did_else_ && builder_->current_block()->IsFinished())) {
// Deopt on false. Nothing to do except switching to the true block.
builder_->set_current_block(last_true_block_);
} else {
@@ -906,6 +907,24 @@
header_block_ = builder->CreateLoopHeaderBlock();
body_block_ = NULL;
exit_block_ = NULL;
+ exit_trampoline_block_ = NULL;
+ increment_amount_ = builder_->graph()->GetConstant1();
+}
+
+
+HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
+ HValue* context,
+ LoopBuilder::Direction direction,
+ HValue* increment_amount)
+ : builder_(builder),
+ context_(context),
+ direction_(direction),
+ finished_(false) {
+ header_block_ = builder->CreateLoopHeaderBlock();
+ body_block_ = NULL;
+ exit_block_ = NULL;
+ exit_trampoline_block_ = NULL;
+ increment_amount_ = increment_amount;
}
@@ -921,12 +940,14 @@
HEnvironment* body_env = env->Copy();
HEnvironment* exit_env = env->Copy();
- body_block_ = builder_->CreateBasicBlock(body_env);
- exit_block_ = builder_->CreateBasicBlock(exit_env);
// Remove the phi from the expression stack
body_env->Pop();
+ exit_env->Pop();
+ body_block_ = builder_->CreateBasicBlock(body_env);
+ exit_block_ = builder_->CreateBasicBlock(exit_env);
builder_->set_current_block(header_block_);
+ env->Pop();
HCompareNumericAndBranch* compare =
new(zone()) HCompareNumericAndBranch(phi_, terminating, token);
compare->SetSuccessorAt(0, body_block_);
@@ -947,6 +968,18 @@
} else {
return phi_;
}
+}
+
+
+void HGraphBuilder::LoopBuilder::Break() {
+ if (exit_trampoline_block_ == NULL) {
+ // Its the first time we saw a break.
+ HEnvironment* env = exit_block_->last_environment()->Copy();
+ exit_trampoline_block_ = builder_->CreateBasicBlock(env);
+ exit_block_->GotoNoSimulate(exit_trampoline_block_);
+ }
+
+ builder_->current_block()->GotoNoSimulate(exit_trampoline_block_);
}
@@ -954,11 +987,10 @@
ASSERT(!finished_);
if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
- HValue* one = builder_->graph()->GetConstant1();
if (direction_ == kPostIncrement) {
- increment_ = HAdd::New(zone(), context_, phi_, one);
+ increment_ = HAdd::New(zone(), context_, phi_, increment_amount_);
} else {
- increment_ = HSub::New(zone(), context_, phi_, one);
+ increment_ = HSub::New(zone(), context_, phi_, increment_amount_);
}
increment_->ClearFlag(HValue::kCanOverflow);
builder_->AddInstruction(increment_);
@@ -970,9 +1002,11 @@
last_block->GotoNoSimulate(header_block_);
header_block_->loop_information()->RegisterBackEdge(last_block);
- builder_->set_current_block(exit_block_);
- // Pop the phi from the expression stack
- builder_->environment()->Pop();
+ if (exit_trampoline_block_ != NULL) {
+ builder_->set_current_block(exit_trampoline_block_);
+ } else {
+ builder_->set_current_block(exit_block_);
+ }
finished_ = true;
}
=======================================
--- /branches/bleeding_edge/src/hydrogen.h Tue Aug 27 11:44:45 2013 UTC
+++ /branches/bleeding_edge/src/hydrogen.h Tue Aug 27 11:55:08 2013 UTC
@@ -1412,6 +1412,11 @@
LoopBuilder(HGraphBuilder* builder,
HValue* context,
Direction direction);
+ LoopBuilder(HGraphBuilder* builder,
+ HValue* context,
+ Direction direction,
+ HValue* increment_amount);
+
~LoopBuilder() {
ASSERT(finished_);
}
@@ -1420,6 +1425,9 @@
HValue* initial,
HValue* terminating,
Token::Value token);
+
+ void Break();
+
void EndBody();
private:
@@ -1427,11 +1435,13 @@
HGraphBuilder* builder_;
HValue* context_;
+ HValue* increment_amount_;
HInstruction* increment_;
HPhi* phi_;
HBasicBlock* header_block_;
HBasicBlock* body_block_;
HBasicBlock* exit_block_;
+ HBasicBlock* exit_trampoline_block_;
Direction direction_;
bool finished_;
};
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri Aug 23 11:06:49
2013 UTC
+++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Tue Aug 27 11:55:08
2013 UTC
@@ -41,6 +41,17 @@
namespace v8 {
namespace internal {
+
+
+void FastNewClosureStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { ebx };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry;
+}
void ToNumberStub::InitializeInterfaceDescriptor(
@@ -297,133 +308,6 @@
__ ret(0);
}
-
-
-void FastNewClosureStub::Generate(MacroAssembler* masm) {
- // Create a new closure from the given function info in new
- // space. Set the context to the current context in esi.
- Counters* counters = masm->isolate()->counters();
-
- Label gc;
- __ Allocate(JSFunction::kSize, eax, ebx, ecx, &gc, TAG_OBJECT);
-
- __ IncrementCounter(counters->fast_new_closure_total(), 1);
-
- // Get the function info from the stack.
- __ mov(edx, Operand(esp, 1 * kPointerSize));
-
- int map_index = Context::FunctionMapIndex(language_mode_, is_generator_);
-
- // Compute the function map in the current native context and set that
- // as the map of the allocated object.
- __ mov(ecx, Operand(esi,
Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
- __ mov(ecx, FieldOperand(ecx, GlobalObject::kNativeContextOffset));
- __ mov(ebx, Operand(ecx, Context::SlotOffset(map_index)));
- __ mov(FieldOperand(eax, JSObject::kMapOffset), ebx);
-
- // Initialize the rest of the function. We don't have to update the
- // write barrier because the allocated object is in new space.
- Factory* factory = masm->isolate()->factory();
- __ mov(ebx, Immediate(factory->empty_fixed_array()));
- __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ebx);
- __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx);
- __ mov(FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset),
- Immediate(factory->the_hole_value()));
- __ mov(FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset), edx);
- __ mov(FieldOperand(eax, JSFunction::kContextOffset), esi);
- __ mov(FieldOperand(eax, JSFunction::kLiteralsOffset), ebx);
-
- // 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.
- Label check_optimized;
- Label install_unoptimized;
- if (FLAG_cache_optimized_code) {
- __ mov(ebx, FieldOperand(edx,
SharedFunctionInfo::kOptimizedCodeMapOffset));
- __ test(ebx, ebx);
- __ j(not_zero, &check_optimized, Label::kNear);
- }
- __ bind(&install_unoptimized);
- __ mov(FieldOperand(eax, JSFunction::kNextFunctionLinkOffset),
- Immediate(factory->undefined_value()));
- __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
- __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
- __ mov(FieldOperand(eax, JSFunction::kCodeEntryOffset), edx);
-
- // Return and remove the on-stack parameter.
- __ ret(1 * kPointerSize);
-
- __ bind(&check_optimized);
-
- __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1);
-
- // ecx holds native context, ebx 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;
- // Speculatively move code object into edx.
- __ mov(edx, FieldOperand(ebx, SharedFunctionInfo::kFirstCodeSlot));
- __ cmp(ecx, FieldOperand(ebx, SharedFunctionInfo::kFirstContextSlot));
- __ j(equal, &install_optimized);
-
- // Iterate through the rest of map backwards. edx holds an index as a
Smi.
- Label loop;
- Label restore;
- __ mov(edx, FieldOperand(ebx, FixedArray::kLengthOffset));
- __ bind(&loop);
- // Do not double check first entry.
- __ cmp(edx,
Immediate(Smi::FromInt(SharedFunctionInfo::kSecondEntryIndex)));
- __ j(equal, &restore);
- __ sub(edx, Immediate(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
- __ cmp(ecx, CodeGenerator::FixedArrayElementOperand(ebx, edx, 0));
- __ j(not_equal, &loop, Label::kNear);
- // Hit: fetch the optimized code.
- __ mov(edx, CodeGenerator::FixedArrayElementOperand(ebx, edx, 1));
-
- __ bind(&install_optimized);
- __ IncrementCounter(counters->fast_new_closure_install_optimized(), 1);
-
- // 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.
- __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
- __ mov(FieldOperand(eax, JSFunction::kCodeEntryOffset), edx);
-
- // Now link a function into a list of optimized functions.
- __ mov(edx, ContextOperand(ecx, Context::OPTIMIZED_FUNCTIONS_LIST));
-
- __ mov(FieldOperand(eax, JSFunction::kNextFunctionLinkOffset), edx);
- // No need for write barrier as JSFunction (eax) is in the new space.
-
- __ mov(ContextOperand(ecx, Context::OPTIMIZED_FUNCTIONS_LIST), eax);
- // Store JSFunction (eax) into edx before issuing write barrier as
- // it clobbers all the registers passed.
- __ mov(edx, eax);
- __ RecordWriteContextSlot(
- ecx,
- Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST),
- edx,
- ebx,
- kDontSaveFPRegs);
-
- // Return and remove the on-stack parameter.
- __ ret(1 * kPointerSize);
-
- __ bind(&restore);
- // Restore SharedFunctionInfo into edx.
- __ mov(edx, Operand(esp, 1 * kPointerSize));
- __ jmp(&install_unoptimized);
-
- // Create a new closure through the slower runtime call.
- __ bind(&gc);
- __ pop(ecx); // Temporarily remove return address.
- __ pop(edx);
- __ push(esi);
- __ push(edx);
- __ push(Immediate(factory->false_value()));
- __ push(ecx); // Restore return address.
- __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
-}
void FastNewContextStub::Generate(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Aug 23
11:31:18 2013 UTC
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Tue Aug 27
11:55:08 2013 UTC
@@ -1268,7 +1268,7 @@
scope()->is_function_scope() &&
info->num_literals() == 0) {
FastNewClosureStub stub(info->language_mode(), info->is_generator());
- __ push(Immediate(info));
+ __ mov(ebx, Immediate(info));
__ CallStub(&stub);
} else {
__ push(esi);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Mon Aug 26
16:48:23 2013 UTC
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Aug 27
11:55:08 2013 UTC
@@ -4347,6 +4347,14 @@
void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
CallRuntime(instr->function(), instr->arity(), instr);
}
+
+
+void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
+ Register function = ToRegister(instr->function());
+ Register code_object = ToRegister(instr->code_object());
+ __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize));
+ __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset),
code_object);
+}
void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
@@ -6209,7 +6217,7 @@
if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(instr->hydrogen()->language_mode(),
instr->hydrogen()->is_generator());
- __ push(Immediate(instr->hydrogen()->shared_info()));
+ __ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
} else {
__ push(esi);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Mon Aug 26 17:30:41
2013 UTC
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Tue Aug 27 11:55:08
2013 UTC
@@ -288,6 +288,14 @@
*hydrogen()->type_literal()->ToCString(),
true_block_id(), false_block_id());
}
+
+
+void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
+ stream->Add(" = ");
+ function()->PrintTo(stream);
+ stream->Add(".code_entry = ");
+ code_object()->PrintTo(stream);
+}
void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
@@ -1148,6 +1156,14 @@
LOperand* argument = UseAny(instr->argument());
return new(zone()) LPushArgument(argument);
}
+
+
+LInstruction* LChunkBuilder::DoStoreCodeEntry(
+ HStoreCodeEntry* store_code_entry) {
+ LOperand* function = UseRegister(store_code_entry->function());
+ LOperand* code_object = UseTempRegister(store_code_entry->code_object());
+ return new(zone()) LStoreCodeEntry(function, code_object);
+}
LInstruction* LChunkBuilder::DoInnerAllocatedObject(
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h Tue Aug 20 13:01:54
2013 UTC
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h Tue Aug 27 11:55:08
2013 UTC
@@ -161,6 +161,7 @@
V(SmiTag) \
V(SmiUntag) \
V(StackCheck) \
+ V(StoreCodeEntry) \
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
@@ -1777,7 +1778,24 @@
};
-class LInnerAllocatedObject V8_FINAL : public LTemplateInstruction<1, 1,
0> {
+class LStoreCodeEntry V8_FINAL: public LTemplateInstruction<0, 1, 1> {
+ public:
+ LStoreCodeEntry(LOperand* function, LOperand* code_object) {
+ inputs_[0] = function;
+ temps_[0] = code_object;
+ }
+
+ LOperand* function() { return inputs_[0]; }
+ LOperand* code_object() { return temps_[0]; }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
+ DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
+};
+
+
+class LInnerAllocatedObject V8_FINAL: public LTemplateInstruction<1, 1, 0>
{
public:
explicit LInnerAllocatedObject(LOperand* base_object) {
inputs_[0] = base_object;
=======================================
--- /branches/bleeding_edge/src/isolate.cc Tue Aug 27 11:47:52 2013 UTC
+++ /branches/bleeding_edge/src/isolate.cc Tue Aug 27 11:55:08 2013 UTC
@@ -2325,6 +2325,7 @@
ToBooleanStub::InitializeForIsolate(this);
ArrayConstructorStubBase::InstallDescriptors(this);
InternalArrayConstructorStubBase::InstallDescriptors(this);
+ FastNewClosureStub::InstallDescriptors(this);
}
if (FLAG_concurrent_recompilation) optimizing_compiler_thread_.Start();
=======================================
--- /branches/bleeding_edge/src/runtime.cc Mon Aug 26 11:59:14 2013 UTC
+++ /branches/bleeding_edge/src/runtime.cc Tue Aug 27 11:55:08 2013 UTC
@@ -7949,6 +7949,20 @@
}
return result;
}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosureFromStubFailure) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
+ Handle<Context> context(isolate->context());
+ PretenureFlag pretenure_flag = NOT_TENURED;
+ Handle<JSFunction> result =
+ isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
+ context,
+
pretenure_flag);
+ return *result;
+}
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
=======================================
--- /branches/bleeding_edge/src/runtime.h Mon Aug 26 11:59:14 2013 UTC
+++ /branches/bleeding_edge/src/runtime.h Tue Aug 27 11:55:08 2013 UTC
@@ -395,6 +395,7 @@
\
/* Statements */ \
F(NewClosure, 3, 1) \
+ F(NewClosureFromStubFailure, 1, 1) \
F(NewObject, 1, 1) \
F(NewObjectFromBound, 1, 1) \
F(FinalizeInstanceSize, 1, 1) \
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Tue Aug 27 01:21:39
2013 UTC
+++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Tue Aug 27 11:55:08
2013 UTC
@@ -37,6 +37,17 @@
namespace v8 {
namespace internal {
+
+
+void FastNewClosureStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { rbx };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry;
+}
void ToNumberStub::InitializeInterfaceDescriptor(
@@ -293,141 +304,6 @@
__ Ret();
}
-
-
-void FastNewClosureStub::Generate(MacroAssembler* masm) {
- // Create a new closure from the given function info in new
- // space. Set the context to the current context in rsi.
- Counters* counters = masm->isolate()->counters();
-
- Label gc;
- __ Allocate(JSFunction::kSize, rax, rbx, rcx, &gc, TAG_OBJECT);
-
- __ IncrementCounter(counters->fast_new_closure_total(), 1);
-
- // Get the function info from the stack.
- StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
- __ movq(rdx, args.GetArgumentOperand(0));
-
- int map_index = Context::FunctionMapIndex(language_mode_, is_generator_);
-
- // Compute the function map in the current native context and set that
- // as the map of the allocated object.
- __ movq(rcx, Operand(rsi,
Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
- __ movq(rcx, FieldOperand(rcx, GlobalObject::kNativeContextOffset));
- __ movq(rbx, Operand(rcx, Context::SlotOffset(map_index)));
- __ movq(FieldOperand(rax, JSObject::kMapOffset), rbx);
-
- // Initialize the rest of the function. We don't have to update the
- // write barrier because the allocated object is in new space.
- __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
- __ LoadRoot(r8, Heap::kTheHoleValueRootIndex);
- __ LoadRoot(rdi, Heap::kUndefinedValueRootIndex);
- __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), rbx);
- __ movq(FieldOperand(rax, JSObject::kElementsOffset), rbx);
- __ movq(FieldOperand(rax, JSFunction::kPrototypeOrInitialMapOffset), r8);
- __ movq(FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset), rdx);
- __ movq(FieldOperand(rax, JSFunction::kContextOffset), rsi);
- __ movq(FieldOperand(rax, JSFunction::kLiteralsOffset), rbx);
-
- // 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.
- Label check_optimized;
- Label install_unoptimized;
- if (FLAG_cache_optimized_code) {
- __ movq(rbx,
- FieldOperand(rdx,
SharedFunctionInfo::kOptimizedCodeMapOffset));
- __ testq(rbx, rbx);
- __ j(not_zero, &check_optimized, Label::kNear);
- }
- __ bind(&install_unoptimized);
- __ movq(FieldOperand(rax, JSFunction::kNextFunctionLinkOffset),
- rdi); // Initialize with undefined.
- __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
- __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
- __ movq(FieldOperand(rax, JSFunction::kCodeEntryOffset), rdx);
-
- // Return and remove the on-stack parameter.
- __ ret(1 * kPointerSize);
-
- __ bind(&check_optimized);
-
- __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1);
-
- // rcx holds native context, rbx points to fixed array of 3-element
entries
- // (native context, optimized code, literals).
- // The optimized code map must never be empty, so check the first
elements.
- Label install_optimized;
- // Speculatively move code object into edx.
- __ movq(rdx, FieldOperand(rbx, SharedFunctionInfo::kFirstCodeSlot));
- __ cmpq(rcx, FieldOperand(rbx, SharedFunctionInfo::kFirstContextSlot));
- __ j(equal, &install_optimized);
-
- // Iterate through the rest of map backwards. rdx holds an index.
- Label loop;
- Label restore;
- __ movq(rdx, FieldOperand(rbx, FixedArray::kLengthOffset));
- __ SmiToInteger32(rdx, rdx);
- __ bind(&loop);
- // Do not double check first entry.
- __ cmpq(rdx, Immediate(SharedFunctionInfo::kSecondEntryIndex));
- __ j(equal, &restore);
- __ subq(rdx, Immediate(SharedFunctionInfo::kEntryLength));
- __ cmpq(rcx, FieldOperand(rbx,
- rdx,
- times_pointer_size,
- FixedArray::kHeaderSize));
- __ j(not_equal, &loop, Label::kNear);
- // Hit: fetch the optimized code.
- __ movq(rdx, FieldOperand(rbx,
- rdx,
- times_pointer_size,
- FixedArray::kHeaderSize + 1 * kPointerSize));
-
- __ bind(&install_optimized);
- __ IncrementCounter(counters->fast_new_closure_install_optimized(), 1);
-
- // TODO(fschneider): Idea: store proper code pointers in the map and
either
- // unmangle them on marking or do nothing as the whole map is discarded
on
- // major GC anyway.
- __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
- __ movq(FieldOperand(rax, JSFunction::kCodeEntryOffset), rdx);
-
- // Now link a function into a list of optimized functions.
- __ movq(rdx, ContextOperand(rcx, Context::OPTIMIZED_FUNCTIONS_LIST));
-
- __ movq(FieldOperand(rax, JSFunction::kNextFunctionLinkOffset), rdx);
- // No need for write barrier as JSFunction (rax) is in the new space.
-
- __ movq(ContextOperand(rcx, Context::OPTIMIZED_FUNCTIONS_LIST), rax);
- // Store JSFunction (rax) into rdx before issuing write barrier as
- // it clobbers all the registers passed.
- __ movq(rdx, rax);
- __ RecordWriteContextSlot(
- rcx,
- Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST),
- rdx,
- rbx,
- kDontSaveFPRegs);
-
- // Return and remove the on-stack parameter.
- __ ret(1 * kPointerSize);
-
- __ bind(&restore);
- __ movq(rdx, args.GetArgumentOperand(0));
- __ jmp(&install_unoptimized);
-
- // Create a new closure through the slower runtime call.
- __ bind(&gc);
- __ PopReturnAddressTo(rcx);
- __ pop(rdx);
- __ push(rsi);
- __ push(rdx);
- __ PushRoot(Heap::kFalseValueRootIndex);
- __ PushReturnAddressFrom(rcx);
- __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
-}
void FastNewContextStub::Generate(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Fri Aug 23 11:31:18
2013 UTC
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Tue Aug 27 11:55:08
2013 UTC
@@ -1292,7 +1292,7 @@
scope()->is_function_scope() &&
info->num_literals() == 0) {
FastNewClosureStub stub(info->language_mode(), info->is_generator());
- __ Push(info);
+ __ Move(rbx, info);
__ CallStub(&stub);
} else {
__ push(rsi);
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue Aug 20
13:57:01 2013 UTC
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue Aug 27
11:55:08 2013 UTC
@@ -3904,6 +3904,14 @@
void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
CallRuntime(instr->function(), instr->arity(), instr);
}
+
+
+void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
+ Register function = ToRegister(instr->function());
+ Register code_object = ToRegister(instr->code_object());
+ __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize));
+ __ movq(FieldOperand(function, JSFunction::kCodeEntryOffset),
code_object);
+}
void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
@@ -5167,7 +5175,7 @@
if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(instr->hydrogen()->language_mode(),
instr->hydrogen()->is_generator());
- __ Push(instr->hydrogen()->shared_info());
+ __ Move(rbx, instr->hydrogen()->shared_info());
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
} else {
__ push(rsi);
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc Mon Aug 26 17:30:41 2013
UTC
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc Tue Aug 27 11:55:08 2013
UTC
@@ -261,6 +261,14 @@
*hydrogen()->type_literal()->ToCString(),
true_block_id(), false_block_id());
}
+
+
+void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
+ stream->Add(" = ");
+ function()->PrintTo(stream);
+ stream->Add(".code_entry = ");
+ code_object()->PrintTo(stream);
+}
void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
@@ -1081,6 +1089,14 @@
LOperand* argument = UseOrConstant(instr->argument());
return new(zone()) LPushArgument(argument);
}
+
+
+LInstruction* LChunkBuilder::DoStoreCodeEntry(
+ HStoreCodeEntry* store_code_entry) {
+ LOperand* function = UseRegister(store_code_entry->function());
+ LOperand* code_object = UseTempRegister(store_code_entry->code_object());
+ return new(zone()) LStoreCodeEntry(function, code_object);
+}
LInstruction* LChunkBuilder::DoInnerAllocatedObject(
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h Tue Aug 20 11:10:24 2013
UTC
+++ /branches/bleeding_edge/src/x64/lithium-x64.h Tue Aug 27 11:55:08 2013
UTC
@@ -160,6 +160,7 @@
V(SmiTag) \
V(SmiUntag) \
V(StackCheck) \
+ V(StoreCodeEntry) \
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
@@ -1693,7 +1694,24 @@
};
-class LInnerAllocatedObject V8_FINAL : public LTemplateInstruction<1, 1,
0> {
+class LStoreCodeEntry V8_FINAL: public LTemplateInstruction<0, 1, 1> {
+ public:
+ LStoreCodeEntry(LOperand* function, LOperand* code_object) {
+ inputs_[0] = function;
+ temps_[0] = code_object;
+ }
+
+ LOperand* function() { return inputs_[0]; }
+ LOperand* code_object() { return temps_[0]; }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
+ DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
+};
+
+
+class LInnerAllocatedObject V8_FINAL: public LTemplateInstruction<1, 1, 0>
{
public:
explicit LInnerAllocatedObject(LOperand* base_object) {
inputs_[0] = base_object;
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.