Remove the uses of the arguments from all calls.

Before, Hydrogen call instructions had uses of the PushArgument instructions
for their arguments.  These operands were unneeded, bloated the IR, and
caused calls to be the only Hydrogen instructions with an unpredictable
number of operands.

Now, PushArgument is a pure side-effecting instruction that has no uses.

Review URL: http://codereview.chromium.org/6480030

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6749 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2011-02-11 13:20:06 +00:00
parent bbba0dbd61
commit 3ef7ca6c28
4 changed files with 183 additions and 322 deletions

View File

@ -290,61 +290,6 @@ void HLoadKeyedGeneric::InternalSetOperandAt(int index, HValue* value) {
} }
void HCallKeyed::InternalSetOperandAt(int index, HValue* value) {
// The key and all the arguments are stored in the base class's arguments_
// vector. The context is in the object itself. Ugly.
if (index <= argument_count()) {
arguments_[index] = value;
} else {
context_ = value;
}
}
void HCallNamed::InternalSetOperandAt(int index, HValue* value) {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
if (index < argument_count()) {
arguments_[index] = value;
} else {
context_ = value;
}
}
void HCallFunction::InternalSetOperandAt(int index, HValue* value) {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
if (index < argument_count()) {
arguments_[index] = value;
} else {
context_ = value;
}
}
void HCallGlobal::InternalSetOperandAt(int index, HValue* value) {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
if (index < argument_count()) {
arguments_[index] = value;
} else {
context_ = value;
}
}
void HCallNew::InternalSetOperandAt(int index, HValue* value) {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
if (index < argument_count()) {
arguments_[index] = value;
} else {
context_ = value;
}
}
void HStoreKeyedGeneric::InternalSetOperandAt(int index, HValue* value) { void HStoreKeyedGeneric::InternalSetOperandAt(int index, HValue* value) {
if (index < 3) { if (index < 3) {
operands_[index] = value; operands_[index] = value;
@ -609,26 +554,64 @@ void HInstruction::Verify() {
#endif #endif
HCall::HCall(int count) : arguments_(Zone::NewArray<HValue*>(count), count) { void HCall::PrintDataTo(StringStream* stream) const {
for (int i = 0; i < count; ++i) arguments_[i] = NULL; stream->Add("#%d", argument_count());
set_representation(Representation::Tagged());
SetAllSideEffects();
} }
void HCall::PrintDataTo(StringStream* stream) const { void HUnaryCall::PrintDataTo(StringStream* stream) const {
stream->Add("("); value()->PrintNameTo(stream);
for (int i = 0; i < arguments_.length(); ++i) { stream->Add(" ");
if (i != 0) stream->Add(", "); HCall::PrintDataTo(stream);
arguments_.at(i)->PrintNameTo(stream); }
void HBinaryCall::PrintDataTo(StringStream* stream) const {
first()->PrintNameTo(stream);
stream->Add(" ");
second()->PrintNameTo(stream);
stream->Add(" ");
HCall::PrintDataTo(stream);
}
void HCallConstantFunction::PrintDataTo(StringStream* stream) const {
if (IsApplyFunction()) {
stream->Add("optimized apply ");
} else {
stream->Add("%o ", function()->shared()->DebugName());
} }
stream->Add(")"); HCall::PrintDataTo(stream);
}
void HCallNamed::PrintDataTo(StringStream* stream) const {
stream->Add("%o ", *name());
HUnaryCall::PrintDataTo(stream);
}
void HCallGlobal::PrintDataTo(StringStream* stream) const {
stream->Add("%o ", *name());
HUnaryCall::PrintDataTo(stream);
}
void HCallKnownGlobal::PrintDataTo(StringStream* stream) const {
stream->Add("o ", target()->shared()->DebugName());
HCall::PrintDataTo(stream);
}
void HCallRuntime::PrintDataTo(StringStream* stream) const {
stream->Add("%o ", *name());
HCall::PrintDataTo(stream);
} }
void HClassOfTest::PrintDataTo(StringStream* stream) const { void HClassOfTest::PrintDataTo(StringStream* stream) const {
stream->Add("class_of_test("); stream->Add("class_of_test(");
value()->PrintTo(stream); value()->PrintNameTo(stream);
stream->Add(", \"%o\")", *class_name()); stream->Add(", \"%o\")", *class_name());
} }
@ -642,22 +625,6 @@ void HAccessArgumentsAt::PrintDataTo(StringStream* stream) const {
} }
void HCall::SetArgumentAt(int index, HPushArgument* push_argument) {
push_argument->set_argument_index(index);
SetOperandAt(index, push_argument);
}
void HCallConstantFunction::PrintDataTo(StringStream* stream) const {
if (IsApplyFunction()) {
stream->Add("SPECIAL function: apply");
} else {
stream->Add("%s", *(function()->shared()->DebugName()->ToCString()));
}
HCall::PrintDataTo(stream);
}
void HControlInstruction::PrintDataTo(StringStream* stream) const { void HControlInstruction::PrintDataTo(StringStream* stream) const {
if (FirstSuccessor() != NULL) { if (FirstSuccessor() != NULL) {
int first_id = FirstSuccessor()->block_id(); int first_id = FirstSuccessor()->block_id();
@ -745,14 +712,6 @@ void HTypeofIs::PrintDataTo(StringStream* stream) const {
} }
void HPushArgument::PrintDataTo(StringStream* stream) const {
HUnaryOperation::PrintDataTo(stream);
if (argument_index() != -1) {
stream->Add(" [%d]", argument_index_);
}
}
void HChange::PrintDataTo(StringStream* stream) const { void HChange::PrintDataTo(StringStream* stream) const {
HUnaryOperation::PrintDataTo(stream); HUnaryOperation::PrintDataTo(stream);
stream->Add(" %s to %s", from_.Mnemonic(), to_.Mnemonic()); stream->Add(" %s to %s", from_.Mnemonic(), to_.Mnemonic());
@ -787,44 +746,10 @@ void HCheckFunction::PrintDataTo(StringStream* stream) const {
} }
void HCallKeyed::PrintDataTo(StringStream* stream) const {
stream->Add("[");
key()->PrintNameTo(stream);
stream->Add("](");
for (int i = 1; i < arguments_.length(); ++i) {
if (i != 1) stream->Add(", ");
arguments_.at(i)->PrintNameTo(stream);
}
stream->Add(")");
}
void HCallNamed::PrintDataTo(StringStream* stream) const {
SmartPointer<char> name_string = name()->ToCString();
stream->Add("%s ", *name_string);
HCall::PrintDataTo(stream);
}
void HCallGlobal::PrintDataTo(StringStream* stream) const {
SmartPointer<char> name_string = name()->ToCString();
stream->Add("%s ", *name_string);
HCall::PrintDataTo(stream);
}
void HCallRuntime::PrintDataTo(StringStream* stream) const {
SmartPointer<char> name_string = name()->ToCString();
stream->Add("%s ", *name_string);
HCall::PrintDataTo(stream);
}
void HCallStub::PrintDataTo(StringStream* stream) const { void HCallStub::PrintDataTo(StringStream* stream) const {
HUnaryOperation::PrintDataTo(stream); stream->Add("%s ",
stream->Add(" %s(%d)", CodeStub::MajorName(major_key_, false));
CodeStub::MajorName(major_key_, false), HUnaryCall::PrintDataTo(stream);
argument_count_);
} }

View File

@ -48,6 +48,7 @@ class LChunkBuilder;
#define HYDROGEN_ALL_INSTRUCTION_LIST(V) \ #define HYDROGEN_ALL_INSTRUCTION_LIST(V) \
V(ArithmeticBinaryOperation) \ V(ArithmeticBinaryOperation) \
V(BinaryCall) \
V(BinaryOperation) \ V(BinaryOperation) \
V(BitwiseBinaryOperation) \ V(BitwiseBinaryOperation) \
V(Call) \ V(Call) \
@ -58,6 +59,7 @@ class LChunkBuilder;
V(Phi) \ V(Phi) \
V(StoreKeyed) \ V(StoreKeyed) \
V(StoreNamed) \ V(StoreNamed) \
V(UnaryCall) \
V(UnaryControlInstruction) \ V(UnaryControlInstruction) \
V(UnaryOperation) \ V(UnaryOperation) \
HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
@ -1049,27 +1051,15 @@ class HLeaveInlined: public HInstruction {
class HPushArgument: public HUnaryOperation { class HPushArgument: public HUnaryOperation {
public: public:
explicit HPushArgument(HValue* value) explicit HPushArgument(HValue* value) : HUnaryOperation(value) { }
: HUnaryOperation(value), argument_index_(-1) {
set_representation(Representation::Tagged());
}
virtual Representation RequiredInputRepresentation(int index) const { virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged(); return Representation::Tagged();
} }
virtual void PrintDataTo(StringStream* stream) const;
HValue* argument() const { return OperandAt(0); } HValue* argument() const { return OperandAt(0); }
int argument_index() const { return argument_index_; }
void set_argument_index(int index) {
ASSERT(argument_index_ == -1 || index == argument_index_);
argument_index_ = index;
}
DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument") DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
private:
int argument_index_;
}; };
@ -1132,36 +1122,80 @@ class HGlobalReceiver: public HUnaryOperation {
class HCall: public HInstruction { class HCall: public HInstruction {
public: public:
// Construct a call with uninitialized arguments. The argument count // The argument count includes the receiver.
// includes the receiver. explicit HCall(int argument_count) : argument_count_(argument_count) {
explicit HCall(int count); set_representation(Representation::Tagged());
SetAllSideEffects();
}
virtual HType CalculateInferredType() const { return HType::Tagged(); } virtual HType CalculateInferredType() const { return HType::Tagged(); }
// TODO(3190496): This needs a cleanup. We don't want the arguments virtual int argument_count() const { return argument_count_; }
// be operands of the call instruction. This results in bad code quality.
virtual int argument_count() const { return arguments_.length(); }
virtual int OperandCount() const { return argument_count(); }
virtual HValue* OperandAt(int index) const { return arguments_[index]; }
virtual HPushArgument* PushArgumentAt(int index) const {
return HPushArgument::cast(OperandAt(index));
}
virtual HValue* ArgumentAt(int index) const {
return PushArgumentAt(index)->argument();
}
virtual void SetArgumentAt(int index, HPushArgument* push_argument);
virtual void PrintDataTo(StringStream* stream) const; virtual void PrintDataTo(StringStream* stream) const;
DECLARE_INSTRUCTION(Call) DECLARE_INSTRUCTION(Call)
protected: private:
virtual void InternalSetOperandAt(int index, HValue* value) { int argument_count_;
arguments_[index] = value; };
class HUnaryCall: public HCall {
public:
HUnaryCall(HValue* value, int argument_count)
: HCall(argument_count), value_(NULL) {
SetOperandAt(0, value);
} }
int argument_count_; virtual void PrintDataTo(StringStream* stream) const;
Vector<HValue*> arguments_;
HValue* value() const { return value_; }
virtual int OperandCount() const { return 1; }
virtual HValue* OperandAt(int index) const {
ASSERT(index == 0);
return value_;
}
DECLARE_INSTRUCTION(UnaryCall)
protected:
virtual void InternalSetOperandAt(int index, HValue* value) {
ASSERT(index == 0);
value_ = value;
}
private:
HValue* value_;
};
class HBinaryCall: public HCall {
public:
HBinaryCall(HValue* first, HValue* second, int argument_count)
: HCall(argument_count) {
SetOperandAt(0, first);
SetOperandAt(1, second);
}
virtual void PrintDataTo(StringStream* stream) const;
HValue* first() const { return operands_[0]; }
HValue* second() const { return operands_[1]; }
virtual int OperandCount() const { return 2; }
virtual HValue* OperandAt(int index) const { return operands_[index]; }
DECLARE_INSTRUCTION(BinaryCall)
protected:
virtual void InternalSetOperandAt(int index, HValue* value) {
operands_[index] = value;
}
private:
HOperandVector<2> operands_;
}; };
@ -1171,6 +1205,7 @@ class HCallConstantFunction: public HCall {
: HCall(argument_count), function_(function) { } : HCall(argument_count), function_(function) { }
Handle<JSFunction> function() const { return function_; } Handle<JSFunction> function() const { return function_; }
bool IsApplyFunction() const { bool IsApplyFunction() const {
return function_->code() == Builtins::builtin(Builtins::FunctionApply); return function_->code() == Builtins::builtin(Builtins::FunctionApply);
} }
@ -1184,147 +1219,78 @@ class HCallConstantFunction: public HCall {
}; };
// TODO(3190496): This class uses hacks to get additional operands that ar class HCallKeyed: public HBinaryCall {
// not arguments to work with the current setup. This _needs_ a cleanup.
// (see HCall).
class HCallKeyed: public HCall {
public: public:
HCallKeyed(HValue* context, HValue* key, int argument_count) HCallKeyed(HValue* context, HValue* key, int argument_count)
: HCall(argument_count + 1), context_(NULL) { : HBinaryCall(context, key, argument_count) {
SetOperandAt(0, key);
SetOperandAt(argument_count + 1, context);
} }
virtual Representation RequiredInputRepresentation(int index) const { virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged(); return Representation::Tagged();
} }
virtual void PrintDataTo(StringStream* stream) const; HValue* context() const { return first(); }
HValue* key() const { return second(); }
HValue* key() const { return OperandAt(0); }
HValue* context() const { return context_; }
virtual int argument_count() const { return arguments_.length() - 1; }
virtual int OperandCount() const { return arguments_.length() + 1; }
virtual HValue* OperandAt(int index) const {
// The key and all the arguments are stored in the base class's
// arguments_ vector. The context is in the object itself. Ugly.
return (index <= argument_count()) ? arguments_[index] : context_;
}
virtual HPushArgument* PushArgumentAt(int index) const {
return HPushArgument::cast(OperandAt(index + 1));
}
virtual void SetArgumentAt(int index, HPushArgument* push_argument) {
HCall::SetArgumentAt(index + 1, push_argument);
}
DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed") DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private:
HValue* context_;
}; };
class HCallNamed: public HCall { class HCallNamed: public HUnaryCall {
public: public:
HCallNamed(HValue* context, Handle<String> name, int argument_count) HCallNamed(HValue* context, Handle<String> name, int argument_count)
: HCall(argument_count), context_(NULL), name_(name) { : HUnaryCall(context, argument_count), name_(name) {
SetOperandAt(argument_count, context);
} }
virtual void PrintDataTo(StringStream* stream) const; virtual void PrintDataTo(StringStream* stream) const;
HValue* context() const { return context_; } HValue* context() const { return value(); }
Handle<String> name() const { return name_; } Handle<String> name() const { return name_; }
virtual int OperandCount() const { return arguments_.length() + 1; }
virtual HValue* OperandAt(int index) const {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
return (index < argument_count()) ? arguments_[index] : context_;
}
DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named") DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private: private:
HValue* context_;
Handle<String> name_; Handle<String> name_;
}; };
class HCallFunction: public HCall { class HCallFunction: public HUnaryCall {
public: public:
HCallFunction(HValue* context, int argument_count) HCallFunction(HValue* context, int argument_count)
: HCall(argument_count), context_(NULL) { : HUnaryCall(context, argument_count) {
SetOperandAt(argument_count, context);
} }
HValue* context() const { return context_; } HValue* context() const { return value(); }
virtual int OperandCount() const { return arguments_.length() + 1; }
virtual HValue* OperandAt(int index) const {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
return (index < argument_count()) ? arguments_[index] : context_;
}
DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function") DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private:
HValue* context_;
}; };
class HCallGlobal: public HCall { class HCallGlobal: public HUnaryCall {
public: public:
HCallGlobal(HValue* context, Handle<String> name, int argument_count) HCallGlobal(HValue* context, Handle<String> name, int argument_count)
: HCall(argument_count), context_(NULL), name_(name) { : HUnaryCall(context, argument_count), name_(name) {
SetOperandAt(argument_count, context);
} }
virtual void PrintDataTo(StringStream* stream) const; virtual void PrintDataTo(StringStream* stream) const;
HValue* context() const { return context_; } HValue* context() const { return value(); }
Handle<String> name() const { return name_; } Handle<String> name() const { return name_; }
virtual int OperandCount() const { return arguments_.length() + 1; }
virtual HValue* OperandAt(int index) const {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
return (index < argument_count()) ? arguments_[index] : context_;
}
DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global") DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private: private:
HValue* context_;
Handle<String> name_; Handle<String> name_;
}; };
class HCallKnownGlobal: public HCall { class HCallKnownGlobal: public HCall {
public: public:
HCallKnownGlobal(Handle<JSFunction> target, HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
int argument_count)
: HCall(argument_count), target_(target) { } : HCall(argument_count), target_(target) { }
virtual void PrintDataTo(StringStream* stream) const;
Handle<JSFunction> target() const { return target_; } Handle<JSFunction> target() const { return target_; }
DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global") DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
@ -1334,35 +1300,20 @@ class HCallKnownGlobal: public HCall {
}; };
class HCallNew: public HCall { class HCallNew: public HBinaryCall {
public: public:
HCallNew(HValue* context, int argument_count) HCallNew(HValue* context, HValue* constructor, int argument_count)
: HCall(argument_count), context_(NULL) { : HBinaryCall(context, constructor, argument_count) {
SetOperandAt(argument_count, context);
} }
virtual Representation RequiredInputRepresentation(int index) const { virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged(); return Representation::Tagged();
} }
HValue* context() const { return context_; } HValue* context() const { return first(); }
HValue* constructor() const { return ArgumentAt(0); } HValue* constructor() const { return second(); }
virtual int OperandCount() const { return arguments_.length() + 1; }
virtual HValue* OperandAt(int index) const {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
return (index < argument_count()) ? arguments_[index] : context_;
}
DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new") DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private:
HValue* context_;
}; };
@ -2764,20 +2715,17 @@ class HParameter: public HInstruction {
}; };
class HCallStub: public HUnaryOperation { class HCallStub: public HUnaryCall {
public: public:
HCallStub(HValue* context, CodeStub::Major major_key, int argument_count) HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
: HUnaryOperation(context), : HUnaryCall(context, argument_count),
major_key_(major_key), major_key_(major_key),
argument_count_(argument_count),
transcendental_type_(TranscendentalCache::kNumberOfCaches) { transcendental_type_(TranscendentalCache::kNumberOfCaches) {
set_representation(Representation::Tagged());
SetAllSideEffects();
} }
CodeStub::Major major_key() { return major_key_; } CodeStub::Major major_key() { return major_key_; }
int argument_count() { return argument_count_; }
HValue* context() { return OperandAt(0); } HValue* context() const { return value(); }
void set_transcendental_type(TranscendentalCache::Type transcendental_type) { void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
transcendental_type_ = transcendental_type; transcendental_type_ = transcendental_type;
@ -2785,13 +2733,13 @@ class HCallStub: public HUnaryOperation {
TranscendentalCache::Type transcendental_type() { TranscendentalCache::Type transcendental_type() {
return transcendental_type_; return transcendental_type_;
} }
virtual void PrintDataTo(StringStream* stream) const; virtual void PrintDataTo(StringStream* stream) const;
DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub") DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
private: private:
CodeStub::Major major_key_; CodeStub::Major major_key_;
int argument_count_;
TranscendentalCache::Type transcendental_type_; TranscendentalCache::Type transcendental_type_;
}; };

View File

@ -2193,10 +2193,8 @@ void HGraphBuilder::VisitForControl(Expression* expr,
} }
HValue* HGraphBuilder::VisitArgument(Expression* expr) { void HGraphBuilder::VisitArgument(Expression* expr) {
VisitForValue(expr); VisitForValue(expr);
if (HasStackOverflow() || !subgraph()->HasExit()) return NULL;
return environment()->Top();
} }
@ -2315,29 +2313,15 @@ void HGraphBuilder::PushAndAdd(HInstruction* instr) {
} }
void HGraphBuilder::PushArgumentsForStubCall(int argument_count) { void HGraphBuilder::PreProcessCall(HCall* call) {
const int kMaxStubArguments = 4; int count = call->argument_count();
ASSERT_GE(kMaxStubArguments, argument_count); ZoneList<HValue*> arguments(count);
// Push the arguments on the stack. for (int i = 0; i < count; ++i) {
HValue* arguments[kMaxStubArguments]; arguments.Add(Pop());
for (int i = argument_count - 1; i >= 0; i--) {
arguments[i] = Pop();
}
for (int i = 0; i < argument_count; i++) {
AddInstruction(new HPushArgument(arguments[i]));
}
}
void HGraphBuilder::ProcessCall(HCall* call) {
for (int i = call->argument_count() - 1; i >= 0; --i) {
HValue* value = Pop();
HPushArgument* push = new HPushArgument(value);
call->SetArgumentAt(i, push);
} }
for (int i = 0; i < call->argument_count(); ++i) { while (!arguments.is_empty()) {
AddInstruction(call->PushArgumentAt(i)); AddInstruction(new HPushArgument(arguments.RemoveLast()));
} }
} }
@ -3945,7 +3929,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
CHECK_BAILOUT; CHECK_BAILOUT;
HCall* call = new HCallConstantFunction(expr->target(), argument_count); HCall* call = new HCallConstantFunction(expr->target(), argument_count);
call->set_position(expr->position()); call->set_position(expr->position());
ProcessCall(call); PreProcessCall(call);
PushAndAdd(call); PushAndAdd(call);
} }
subgraphs.Add(subgraph); subgraphs.Add(subgraph);
@ -3961,7 +3945,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
AddInstruction(context); AddInstruction(context);
HCall* call = new HCallNamed(context, name, argument_count); HCall* call = new HCallNamed(context, name, argument_count);
call->set_position(expr->position()); call->set_position(expr->position());
ProcessCall(call); PreProcessCall(call);
ast_context()->ReturnInstruction(call, expr->id()); ast_context()->ReturnInstruction(call, expr->id());
} else { } else {
// Build subgraph for generic call through IC. // Build subgraph for generic call through IC.
@ -3975,7 +3959,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
AddInstruction(context); AddInstruction(context);
HCall* call = new HCallNamed(context, name, argument_count); HCall* call = new HCallNamed(context, name, argument_count);
call->set_position(expr->position()); call->set_position(expr->position());
ProcessCall(call); PreProcessCall(call);
PushAndAdd(call); PushAndAdd(call);
} }
subgraphs.Add(subgraph); subgraphs.Add(subgraph);
@ -4397,7 +4381,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
AddInstruction(context); AddInstruction(context);
call = new HCallKeyed(context, key, argument_count); call = new HCallKeyed(context, key, argument_count);
call->set_position(expr->position()); call->set_position(expr->position());
ProcessCall(call); PreProcessCall(call);
Drop(1); // Key. Drop(1); // Key.
ast_context()->ReturnInstruction(call, expr->id()); ast_context()->ReturnInstruction(call, expr->id());
return; return;
@ -4409,7 +4393,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
if (TryCallApply(expr)) return; if (TryCallApply(expr)) return;
CHECK_BAILOUT; CHECK_BAILOUT;
HValue* receiver = VisitArgument(prop->obj()); VisitArgument(prop->obj());
CHECK_BAILOUT; CHECK_BAILOUT;
VisitArgumentList(expr->arguments()); VisitArgumentList(expr->arguments());
CHECK_BAILOUT; CHECK_BAILOUT;
@ -4419,6 +4403,8 @@ void HGraphBuilder::VisitCall(Call* expr) {
expr->RecordTypeFeedback(oracle()); expr->RecordTypeFeedback(oracle());
ZoneMapList* types = expr->GetReceiverTypes(); ZoneMapList* types = expr->GetReceiverTypes();
HValue* receiver =
environment()->ExpressionStackAt(expr->arguments()->length());
if (expr->IsMonomorphic()) { if (expr->IsMonomorphic()) {
Handle<Map> receiver_map = Handle<Map> receiver_map =
(types == NULL) ? Handle<Map>::null() : types->first(); (types == NULL) ? Handle<Map>::null() : types->first();
@ -4554,7 +4540,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
} }
call->set_position(expr->position()); call->set_position(expr->position());
ProcessCall(call); PreProcessCall(call);
ast_context()->ReturnInstruction(call, expr->id()); ast_context()->ReturnInstruction(call, expr->id());
} }
@ -4567,12 +4553,16 @@ void HGraphBuilder::VisitCallNew(CallNew* expr) {
VisitArgumentList(expr->arguments()); VisitArgumentList(expr->arguments());
CHECK_BAILOUT; CHECK_BAILOUT;
int argument_count = expr->arguments()->length() + 1; // Plus constructor.
HContext* context = new HContext; HContext* context = new HContext;
AddInstruction(context); AddInstruction(context);
HCall* call = new HCallNew(context, argument_count);
// The constructor is both an operand to the instruction and an argument
// to the construct call.
int arg_count = expr->arguments()->length() + 1; // Plus constructor.
HValue* constructor = environment()->ExpressionStackAt(arg_count - 1);
HCall* call = new HCallNew(context, constructor, arg_count);
call->set_position(expr->position()); call->set_position(expr->position());
ProcessCall(call); PreProcessCall(call);
ast_context()->ReturnInstruction(call, expr->id()); ast_context()->ReturnInstruction(call, expr->id());
} }
@ -4626,7 +4616,7 @@ void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
ASSERT(function->intrinsic_type == Runtime::RUNTIME); ASSERT(function->intrinsic_type == Runtime::RUNTIME);
HCall* call = new HCallRuntime(name, expr->function(), argument_count); HCall* call = new HCallRuntime(name, expr->function(), argument_count);
call->set_position(RelocInfo::kNoPosition); call->set_position(RelocInfo::kNoPosition);
ProcessCall(call); PreProcessCall(call);
ast_context()->ReturnInstruction(call, expr->id()); ast_context()->ReturnInstruction(call, expr->id());
} }
} }
@ -5313,11 +5303,11 @@ void HGraphBuilder::GenerateStringCharFromCode(int argument_count,
// Fast support for string.charAt(n) and string[n]. // Fast support for string.charAt(n) and string[n].
void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) { void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) {
ASSERT_EQ(2, argument_count); ASSERT_EQ(2, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext; HContext* context = new HContext;
AddInstruction(context); AddInstruction(context);
HCallStub* result = HCallStub* result =
new HCallStub(context, CodeStub::StringCharAt, argument_count); new HCallStub(context, CodeStub::StringCharAt, argument_count);
PreProcessCall(result);
ast_context()->ReturnInstruction(result, ast_id); ast_context()->ReturnInstruction(result, ast_id);
} }
@ -5346,11 +5336,11 @@ void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) {
// Fast support for StringAdd. // Fast support for StringAdd.
void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) { void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
ASSERT_EQ(2, argument_count); ASSERT_EQ(2, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext; HContext* context = new HContext;
AddInstruction(context); AddInstruction(context);
HCallStub* result = HCallStub* result =
new HCallStub(context, CodeStub::StringAdd, argument_count); new HCallStub(context, CodeStub::StringAdd, argument_count);
PreProcessCall(result);
ast_context()->ReturnInstruction(result, ast_id); ast_context()->ReturnInstruction(result, ast_id);
} }
@ -5358,11 +5348,11 @@ void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
// Fast support for SubString. // Fast support for SubString.
void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) { void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
ASSERT_EQ(3, argument_count); ASSERT_EQ(3, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext; HContext* context = new HContext;
AddInstruction(context); AddInstruction(context);
HCallStub* result = HCallStub* result =
new HCallStub(context, CodeStub::SubString, argument_count); new HCallStub(context, CodeStub::SubString, argument_count);
PreProcessCall(result);
ast_context()->ReturnInstruction(result, ast_id); ast_context()->ReturnInstruction(result, ast_id);
} }
@ -5370,11 +5360,11 @@ void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
// Fast support for StringCompare. // Fast support for StringCompare.
void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) { void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) {
ASSERT_EQ(2, argument_count); ASSERT_EQ(2, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext; HContext* context = new HContext;
AddInstruction(context); AddInstruction(context);
HCallStub* result = HCallStub* result =
new HCallStub(context, CodeStub::StringCompare, argument_count); new HCallStub(context, CodeStub::StringCompare, argument_count);
PreProcessCall(result);
ast_context()->ReturnInstruction(result, ast_id); ast_context()->ReturnInstruction(result, ast_id);
} }
@ -5382,11 +5372,11 @@ void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) {
// Support for direct calls from JavaScript to native RegExp code. // Support for direct calls from JavaScript to native RegExp code.
void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) { void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) {
ASSERT_EQ(4, argument_count); ASSERT_EQ(4, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext; HContext* context = new HContext;
AddInstruction(context); AddInstruction(context);
HCallStub* result = HCallStub* result =
new HCallStub(context, CodeStub::RegExpExec, argument_count); new HCallStub(context, CodeStub::RegExpExec, argument_count);
PreProcessCall(result);
ast_context()->ReturnInstruction(result, ast_id); ast_context()->ReturnInstruction(result, ast_id);
} }
@ -5395,11 +5385,11 @@ void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) {
void HGraphBuilder::GenerateRegExpConstructResult(int argument_count, void HGraphBuilder::GenerateRegExpConstructResult(int argument_count,
int ast_id) { int ast_id) {
ASSERT_EQ(3, argument_count); ASSERT_EQ(3, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext; HContext* context = new HContext;
AddInstruction(context); AddInstruction(context);
HCallStub* result = HCallStub* result =
new HCallStub(context, CodeStub::RegExpConstructResult, argument_count); new HCallStub(context, CodeStub::RegExpConstructResult, argument_count);
PreProcessCall(result);
ast_context()->ReturnInstruction(result, ast_id); ast_context()->ReturnInstruction(result, ast_id);
} }
@ -5413,11 +5403,11 @@ void HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) {
// Fast support for number to string. // Fast support for number to string.
void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) { void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) {
ASSERT_EQ(1, argument_count); ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext; HContext* context = new HContext;
AddInstruction(context); AddInstruction(context);
HCallStub* result = HCallStub* result =
new HCallStub(context, CodeStub::NumberToString, argument_count); new HCallStub(context, CodeStub::NumberToString, argument_count);
PreProcessCall(result);
ast_context()->ReturnInstruction(result, ast_id); ast_context()->ReturnInstruction(result, ast_id);
} }
@ -5448,36 +5438,36 @@ void HGraphBuilder::GenerateMathPow(int argument_count, int ast_id) {
void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) { void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) {
ASSERT_EQ(1, argument_count); ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext; HContext* context = new HContext;
AddInstruction(context); AddInstruction(context);
HCallStub* result = HCallStub* result =
new HCallStub(context, CodeStub::TranscendentalCache, argument_count); new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
result->set_transcendental_type(TranscendentalCache::SIN); result->set_transcendental_type(TranscendentalCache::SIN);
PreProcessCall(result);
ast_context()->ReturnInstruction(result, ast_id); ast_context()->ReturnInstruction(result, ast_id);
} }
void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) { void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) {
ASSERT_EQ(1, argument_count); ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext; HContext* context = new HContext;
AddInstruction(context); AddInstruction(context);
HCallStub* result = HCallStub* result =
new HCallStub(context, CodeStub::TranscendentalCache, argument_count); new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
result->set_transcendental_type(TranscendentalCache::COS); result->set_transcendental_type(TranscendentalCache::COS);
PreProcessCall(result);
ast_context()->ReturnInstruction(result, ast_id); ast_context()->ReturnInstruction(result, ast_id);
} }
void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) { void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) {
ASSERT_EQ(1, argument_count); ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext; HContext* context = new HContext;
AddInstruction(context); AddInstruction(context);
HCallStub* result = HCallStub* result =
new HCallStub(context, CodeStub::TranscendentalCache, argument_count); new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
result->set_transcendental_type(TranscendentalCache::LOG); result->set_transcendental_type(TranscendentalCache::LOG);
PreProcessCall(result);
ast_context()->ReturnInstruction(result, ast_id); ast_context()->ReturnInstruction(result, ast_id);
} }

View File

@ -706,19 +706,17 @@ class HGraphBuilder: public AstVisitor {
HBasicBlock* true_block, HBasicBlock* true_block,
HBasicBlock* false_block); HBasicBlock* false_block);
// Visit an argument and wrap it in a PushArgument instruction. // Visit an argument subexpression.
HValue* VisitArgument(Expression* expr); void VisitArgument(Expression* expr);
void VisitArgumentList(ZoneList<Expression*>* arguments); void VisitArgumentList(ZoneList<Expression*>* arguments);
void AddPhi(HPhi* phi); void AddPhi(HPhi* phi);
void PushAndAdd(HInstruction* instr); void PushAndAdd(HInstruction* instr);
void PushArgumentsForStubCall(int argument_count);
// Remove the arguments from the bailout environment and emit instructions // Remove the arguments from the bailout environment and emit instructions
// to push them as outgoing parameters. // to push them as outgoing parameters.
void ProcessCall(HCall* call); void PreProcessCall(HCall* call);
void AssumeRepresentation(HValue* value, Representation r); void AssumeRepresentation(HValue* value, Representation r);
static Representation ToRepresentation(TypeInfo info); static Representation ToRepresentation(TypeInfo info);