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:
parent
bbba0dbd61
commit
3ef7ca6c28
@ -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) {
|
||||
if (index < 3) {
|
||||
operands_[index] = value;
|
||||
@ -609,26 +554,64 @@ void HInstruction::Verify() {
|
||||
#endif
|
||||
|
||||
|
||||
HCall::HCall(int count) : arguments_(Zone::NewArray<HValue*>(count), count) {
|
||||
for (int i = 0; i < count; ++i) arguments_[i] = NULL;
|
||||
set_representation(Representation::Tagged());
|
||||
SetAllSideEffects();
|
||||
void HCall::PrintDataTo(StringStream* stream) const {
|
||||
stream->Add("#%d", argument_count());
|
||||
}
|
||||
|
||||
|
||||
void HCall::PrintDataTo(StringStream* stream) const {
|
||||
stream->Add("(");
|
||||
for (int i = 0; i < arguments_.length(); ++i) {
|
||||
if (i != 0) stream->Add(", ");
|
||||
arguments_.at(i)->PrintNameTo(stream);
|
||||
void HUnaryCall::PrintDataTo(StringStream* stream) const {
|
||||
value()->PrintNameTo(stream);
|
||||
stream->Add(" ");
|
||||
HCall::PrintDataTo(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 {
|
||||
stream->Add("class_of_test(");
|
||||
value()->PrintTo(stream);
|
||||
value()->PrintNameTo(stream);
|
||||
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 {
|
||||
if (FirstSuccessor() != NULL) {
|
||||
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 {
|
||||
HUnaryOperation::PrintDataTo(stream);
|
||||
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 {
|
||||
HUnaryOperation::PrintDataTo(stream);
|
||||
stream->Add(" %s(%d)",
|
||||
CodeStub::MajorName(major_key_, false),
|
||||
argument_count_);
|
||||
stream->Add("%s ",
|
||||
CodeStub::MajorName(major_key_, false));
|
||||
HUnaryCall::PrintDataTo(stream);
|
||||
}
|
||||
|
||||
|
||||
|
@ -48,6 +48,7 @@ class LChunkBuilder;
|
||||
|
||||
#define HYDROGEN_ALL_INSTRUCTION_LIST(V) \
|
||||
V(ArithmeticBinaryOperation) \
|
||||
V(BinaryCall) \
|
||||
V(BinaryOperation) \
|
||||
V(BitwiseBinaryOperation) \
|
||||
V(Call) \
|
||||
@ -58,6 +59,7 @@ class LChunkBuilder;
|
||||
V(Phi) \
|
||||
V(StoreKeyed) \
|
||||
V(StoreNamed) \
|
||||
V(UnaryCall) \
|
||||
V(UnaryControlInstruction) \
|
||||
V(UnaryOperation) \
|
||||
HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
|
||||
@ -1049,27 +1051,15 @@ class HLeaveInlined: public HInstruction {
|
||||
|
||||
class HPushArgument: public HUnaryOperation {
|
||||
public:
|
||||
explicit HPushArgument(HValue* value)
|
||||
: HUnaryOperation(value), argument_index_(-1) {
|
||||
set_representation(Representation::Tagged());
|
||||
}
|
||||
explicit HPushArgument(HValue* value) : HUnaryOperation(value) { }
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) const {
|
||||
return Representation::Tagged();
|
||||
}
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
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")
|
||||
|
||||
private:
|
||||
int argument_index_;
|
||||
};
|
||||
|
||||
|
||||
@ -1132,36 +1122,80 @@ class HGlobalReceiver: public HUnaryOperation {
|
||||
|
||||
class HCall: public HInstruction {
|
||||
public:
|
||||
// Construct a call with uninitialized arguments. The argument count
|
||||
// includes the receiver.
|
||||
explicit HCall(int count);
|
||||
// The argument count includes the receiver.
|
||||
explicit HCall(int argument_count) : argument_count_(argument_count) {
|
||||
set_representation(Representation::Tagged());
|
||||
SetAllSideEffects();
|
||||
}
|
||||
|
||||
virtual HType CalculateInferredType() const { return HType::Tagged(); }
|
||||
|
||||
// TODO(3190496): This needs a cleanup. We don't want the arguments
|
||||
// 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 int argument_count() const { return argument_count_; }
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
|
||||
DECLARE_INSTRUCTION(Call)
|
||||
|
||||
protected:
|
||||
virtual void InternalSetOperandAt(int index, HValue* value) {
|
||||
arguments_[index] = value;
|
||||
private:
|
||||
int argument_count_;
|
||||
};
|
||||
|
||||
|
||||
class HUnaryCall: public HCall {
|
||||
public:
|
||||
HUnaryCall(HValue* value, int argument_count)
|
||||
: HCall(argument_count), value_(NULL) {
|
||||
SetOperandAt(0, value);
|
||||
}
|
||||
|
||||
int argument_count_;
|
||||
Vector<HValue*> arguments_;
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
|
||||
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) { }
|
||||
|
||||
Handle<JSFunction> function() const { return function_; }
|
||||
|
||||
bool IsApplyFunction() const {
|
||||
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
|
||||
// not arguments to work with the current setup. This _needs_ a cleanup.
|
||||
// (see HCall).
|
||||
class HCallKeyed: public HCall {
|
||||
class HCallKeyed: public HBinaryCall {
|
||||
public:
|
||||
HCallKeyed(HValue* context, HValue* key, int argument_count)
|
||||
: HCall(argument_count + 1), context_(NULL) {
|
||||
SetOperandAt(0, key);
|
||||
SetOperandAt(argument_count + 1, context);
|
||||
: HBinaryCall(context, key, argument_count) {
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) const {
|
||||
return Representation::Tagged();
|
||||
}
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
|
||||
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);
|
||||
}
|
||||
HValue* context() const { return first(); }
|
||||
HValue* key() const { return second(); }
|
||||
|
||||
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:
|
||||
HCallNamed(HValue* context, Handle<String> name, int argument_count)
|
||||
: HCall(argument_count), context_(NULL), name_(name) {
|
||||
SetOperandAt(argument_count, context);
|
||||
: HUnaryCall(context, argument_count), name_(name) {
|
||||
}
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
|
||||
HValue* context() const { return context_; }
|
||||
HValue* context() const { return value(); }
|
||||
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")
|
||||
|
||||
protected:
|
||||
virtual void InternalSetOperandAt(int index, HValue* value);
|
||||
|
||||
private:
|
||||
HValue* context_;
|
||||
Handle<String> name_;
|
||||
};
|
||||
|
||||
|
||||
class HCallFunction: public HCall {
|
||||
class HCallFunction: public HUnaryCall {
|
||||
public:
|
||||
HCallFunction(HValue* context, int argument_count)
|
||||
: HCall(argument_count), context_(NULL) {
|
||||
SetOperandAt(argument_count, context);
|
||||
: HUnaryCall(context, argument_count) {
|
||||
}
|
||||
|
||||
HValue* context() const { return context_; }
|
||||
|
||||
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_;
|
||||
}
|
||||
HValue* context() const { return value(); }
|
||||
|
||||
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:
|
||||
HCallGlobal(HValue* context, Handle<String> name, int argument_count)
|
||||
: HCall(argument_count), context_(NULL), name_(name) {
|
||||
SetOperandAt(argument_count, context);
|
||||
: HUnaryCall(context, argument_count), name_(name) {
|
||||
}
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
|
||||
HValue* context() const { return context_; }
|
||||
HValue* context() const { return value(); }
|
||||
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")
|
||||
|
||||
protected:
|
||||
virtual void InternalSetOperandAt(int index, HValue* value);
|
||||
|
||||
private:
|
||||
HValue* context_;
|
||||
Handle<String> name_;
|
||||
};
|
||||
|
||||
|
||||
class HCallKnownGlobal: public HCall {
|
||||
public:
|
||||
HCallKnownGlobal(Handle<JSFunction> target,
|
||||
int argument_count)
|
||||
HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
|
||||
: HCall(argument_count), target_(target) { }
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
|
||||
Handle<JSFunction> target() const { return target_; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
|
||||
@ -1334,35 +1300,20 @@ class HCallKnownGlobal: public HCall {
|
||||
};
|
||||
|
||||
|
||||
class HCallNew: public HCall {
|
||||
class HCallNew: public HBinaryCall {
|
||||
public:
|
||||
HCallNew(HValue* context, int argument_count)
|
||||
: HCall(argument_count), context_(NULL) {
|
||||
SetOperandAt(argument_count, context);
|
||||
HCallNew(HValue* context, HValue* constructor, int argument_count)
|
||||
: HBinaryCall(context, constructor, argument_count) {
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) const {
|
||||
return Representation::Tagged();
|
||||
}
|
||||
|
||||
HValue* context() const { return context_; }
|
||||
HValue* constructor() const { return ArgumentAt(0); }
|
||||
|
||||
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_;
|
||||
}
|
||||
HValue* context() const { return first(); }
|
||||
HValue* constructor() const { return second(); }
|
||||
|
||||
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:
|
||||
HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
|
||||
: HUnaryOperation(context),
|
||||
: HUnaryCall(context, argument_count),
|
||||
major_key_(major_key),
|
||||
argument_count_(argument_count),
|
||||
transcendental_type_(TranscendentalCache::kNumberOfCaches) {
|
||||
set_representation(Representation::Tagged());
|
||||
SetAllSideEffects();
|
||||
}
|
||||
|
||||
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) {
|
||||
transcendental_type_ = transcendental_type;
|
||||
@ -2785,13 +2733,13 @@ class HCallStub: public HUnaryOperation {
|
||||
TranscendentalCache::Type transcendental_type() {
|
||||
return transcendental_type_;
|
||||
}
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
|
||||
|
||||
private:
|
||||
CodeStub::Major major_key_;
|
||||
int argument_count_;
|
||||
TranscendentalCache::Type transcendental_type_;
|
||||
};
|
||||
|
||||
|
@ -2193,10 +2193,8 @@ void HGraphBuilder::VisitForControl(Expression* expr,
|
||||
}
|
||||
|
||||
|
||||
HValue* HGraphBuilder::VisitArgument(Expression* expr) {
|
||||
void HGraphBuilder::VisitArgument(Expression* 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) {
|
||||
const int kMaxStubArguments = 4;
|
||||
ASSERT_GE(kMaxStubArguments, argument_count);
|
||||
// Push the arguments on the stack.
|
||||
HValue* arguments[kMaxStubArguments];
|
||||
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);
|
||||
void HGraphBuilder::PreProcessCall(HCall* call) {
|
||||
int count = call->argument_count();
|
||||
ZoneList<HValue*> arguments(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
arguments.Add(Pop());
|
||||
}
|
||||
|
||||
for (int i = 0; i < call->argument_count(); ++i) {
|
||||
AddInstruction(call->PushArgumentAt(i));
|
||||
while (!arguments.is_empty()) {
|
||||
AddInstruction(new HPushArgument(arguments.RemoveLast()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3945,7 +3929,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
|
||||
CHECK_BAILOUT;
|
||||
HCall* call = new HCallConstantFunction(expr->target(), argument_count);
|
||||
call->set_position(expr->position());
|
||||
ProcessCall(call);
|
||||
PreProcessCall(call);
|
||||
PushAndAdd(call);
|
||||
}
|
||||
subgraphs.Add(subgraph);
|
||||
@ -3961,7 +3945,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
|
||||
AddInstruction(context);
|
||||
HCall* call = new HCallNamed(context, name, argument_count);
|
||||
call->set_position(expr->position());
|
||||
ProcessCall(call);
|
||||
PreProcessCall(call);
|
||||
ast_context()->ReturnInstruction(call, expr->id());
|
||||
} else {
|
||||
// Build subgraph for generic call through IC.
|
||||
@ -3975,7 +3959,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
|
||||
AddInstruction(context);
|
||||
HCall* call = new HCallNamed(context, name, argument_count);
|
||||
call->set_position(expr->position());
|
||||
ProcessCall(call);
|
||||
PreProcessCall(call);
|
||||
PushAndAdd(call);
|
||||
}
|
||||
subgraphs.Add(subgraph);
|
||||
@ -4397,7 +4381,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
|
||||
AddInstruction(context);
|
||||
call = new HCallKeyed(context, key, argument_count);
|
||||
call->set_position(expr->position());
|
||||
ProcessCall(call);
|
||||
PreProcessCall(call);
|
||||
Drop(1); // Key.
|
||||
ast_context()->ReturnInstruction(call, expr->id());
|
||||
return;
|
||||
@ -4409,7 +4393,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
|
||||
if (TryCallApply(expr)) return;
|
||||
CHECK_BAILOUT;
|
||||
|
||||
HValue* receiver = VisitArgument(prop->obj());
|
||||
VisitArgument(prop->obj());
|
||||
CHECK_BAILOUT;
|
||||
VisitArgumentList(expr->arguments());
|
||||
CHECK_BAILOUT;
|
||||
@ -4419,6 +4403,8 @@ void HGraphBuilder::VisitCall(Call* expr) {
|
||||
expr->RecordTypeFeedback(oracle());
|
||||
ZoneMapList* types = expr->GetReceiverTypes();
|
||||
|
||||
HValue* receiver =
|
||||
environment()->ExpressionStackAt(expr->arguments()->length());
|
||||
if (expr->IsMonomorphic()) {
|
||||
Handle<Map> receiver_map =
|
||||
(types == NULL) ? Handle<Map>::null() : types->first();
|
||||
@ -4554,7 +4540,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
|
||||
}
|
||||
|
||||
call->set_position(expr->position());
|
||||
ProcessCall(call);
|
||||
PreProcessCall(call);
|
||||
ast_context()->ReturnInstruction(call, expr->id());
|
||||
}
|
||||
|
||||
@ -4567,12 +4553,16 @@ void HGraphBuilder::VisitCallNew(CallNew* expr) {
|
||||
VisitArgumentList(expr->arguments());
|
||||
CHECK_BAILOUT;
|
||||
|
||||
int argument_count = expr->arguments()->length() + 1; // Plus constructor.
|
||||
HContext* context = new HContext;
|
||||
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());
|
||||
ProcessCall(call);
|
||||
PreProcessCall(call);
|
||||
ast_context()->ReturnInstruction(call, expr->id());
|
||||
}
|
||||
|
||||
@ -4626,7 +4616,7 @@ void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
|
||||
ASSERT(function->intrinsic_type == Runtime::RUNTIME);
|
||||
HCall* call = new HCallRuntime(name, expr->function(), argument_count);
|
||||
call->set_position(RelocInfo::kNoPosition);
|
||||
ProcessCall(call);
|
||||
PreProcessCall(call);
|
||||
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].
|
||||
void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) {
|
||||
ASSERT_EQ(2, argument_count);
|
||||
PushArgumentsForStubCall(argument_count);
|
||||
HContext* context = new HContext;
|
||||
AddInstruction(context);
|
||||
HCallStub* result =
|
||||
new HCallStub(context, CodeStub::StringCharAt, argument_count);
|
||||
PreProcessCall(result);
|
||||
ast_context()->ReturnInstruction(result, ast_id);
|
||||
}
|
||||
|
||||
@ -5346,11 +5336,11 @@ void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) {
|
||||
// Fast support for StringAdd.
|
||||
void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
|
||||
ASSERT_EQ(2, argument_count);
|
||||
PushArgumentsForStubCall(argument_count);
|
||||
HContext* context = new HContext;
|
||||
AddInstruction(context);
|
||||
HCallStub* result =
|
||||
new HCallStub(context, CodeStub::StringAdd, argument_count);
|
||||
PreProcessCall(result);
|
||||
ast_context()->ReturnInstruction(result, ast_id);
|
||||
}
|
||||
|
||||
@ -5358,11 +5348,11 @@ void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
|
||||
// Fast support for SubString.
|
||||
void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
|
||||
ASSERT_EQ(3, argument_count);
|
||||
PushArgumentsForStubCall(argument_count);
|
||||
HContext* context = new HContext;
|
||||
AddInstruction(context);
|
||||
HCallStub* result =
|
||||
new HCallStub(context, CodeStub::SubString, argument_count);
|
||||
PreProcessCall(result);
|
||||
ast_context()->ReturnInstruction(result, ast_id);
|
||||
}
|
||||
|
||||
@ -5370,11 +5360,11 @@ void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
|
||||
// Fast support for StringCompare.
|
||||
void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) {
|
||||
ASSERT_EQ(2, argument_count);
|
||||
PushArgumentsForStubCall(argument_count);
|
||||
HContext* context = new HContext;
|
||||
AddInstruction(context);
|
||||
HCallStub* result =
|
||||
new HCallStub(context, CodeStub::StringCompare, argument_count);
|
||||
PreProcessCall(result);
|
||||
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.
|
||||
void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) {
|
||||
ASSERT_EQ(4, argument_count);
|
||||
PushArgumentsForStubCall(argument_count);
|
||||
HContext* context = new HContext;
|
||||
AddInstruction(context);
|
||||
HCallStub* result =
|
||||
new HCallStub(context, CodeStub::RegExpExec, argument_count);
|
||||
PreProcessCall(result);
|
||||
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,
|
||||
int ast_id) {
|
||||
ASSERT_EQ(3, argument_count);
|
||||
PushArgumentsForStubCall(argument_count);
|
||||
HContext* context = new HContext;
|
||||
AddInstruction(context);
|
||||
HCallStub* result =
|
||||
new HCallStub(context, CodeStub::RegExpConstructResult, argument_count);
|
||||
PreProcessCall(result);
|
||||
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.
|
||||
void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) {
|
||||
ASSERT_EQ(1, argument_count);
|
||||
PushArgumentsForStubCall(argument_count);
|
||||
HContext* context = new HContext;
|
||||
AddInstruction(context);
|
||||
HCallStub* result =
|
||||
new HCallStub(context, CodeStub::NumberToString, argument_count);
|
||||
PreProcessCall(result);
|
||||
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) {
|
||||
ASSERT_EQ(1, argument_count);
|
||||
PushArgumentsForStubCall(argument_count);
|
||||
HContext* context = new HContext;
|
||||
AddInstruction(context);
|
||||
HCallStub* result =
|
||||
new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
|
||||
result->set_transcendental_type(TranscendentalCache::SIN);
|
||||
PreProcessCall(result);
|
||||
ast_context()->ReturnInstruction(result, ast_id);
|
||||
}
|
||||
|
||||
|
||||
void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) {
|
||||
ASSERT_EQ(1, argument_count);
|
||||
PushArgumentsForStubCall(argument_count);
|
||||
HContext* context = new HContext;
|
||||
AddInstruction(context);
|
||||
HCallStub* result =
|
||||
new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
|
||||
result->set_transcendental_type(TranscendentalCache::COS);
|
||||
PreProcessCall(result);
|
||||
ast_context()->ReturnInstruction(result, ast_id);
|
||||
}
|
||||
|
||||
|
||||
void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) {
|
||||
ASSERT_EQ(1, argument_count);
|
||||
PushArgumentsForStubCall(argument_count);
|
||||
HContext* context = new HContext;
|
||||
AddInstruction(context);
|
||||
HCallStub* result =
|
||||
new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
|
||||
result->set_transcendental_type(TranscendentalCache::LOG);
|
||||
PreProcessCall(result);
|
||||
ast_context()->ReturnInstruction(result, ast_id);
|
||||
}
|
||||
|
||||
|
@ -706,19 +706,17 @@ class HGraphBuilder: public AstVisitor {
|
||||
HBasicBlock* true_block,
|
||||
HBasicBlock* false_block);
|
||||
|
||||
// Visit an argument and wrap it in a PushArgument instruction.
|
||||
HValue* VisitArgument(Expression* expr);
|
||||
// Visit an argument subexpression.
|
||||
void VisitArgument(Expression* expr);
|
||||
void VisitArgumentList(ZoneList<Expression*>* arguments);
|
||||
|
||||
void AddPhi(HPhi* phi);
|
||||
|
||||
void PushAndAdd(HInstruction* instr);
|
||||
|
||||
void PushArgumentsForStubCall(int argument_count);
|
||||
|
||||
// Remove the arguments from the bailout environment and emit instructions
|
||||
// to push them as outgoing parameters.
|
||||
void ProcessCall(HCall* call);
|
||||
void PreProcessCall(HCall* call);
|
||||
|
||||
void AssumeRepresentation(HValue* value, Representation r);
|
||||
static Representation ToRepresentation(TypeInfo info);
|
||||
|
Loading…
Reference in New Issue
Block a user