2011-01-07 09:47:16 +00:00
|
|
|
// Copyright 2011 the V8 project authors. All rights reserved.
|
2010-12-07 11:31:57 +00:00
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are
|
|
|
|
// met:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer.
|
|
|
|
// * Redistributions in binary form must reproduce the above
|
|
|
|
// copyright notice, this list of conditions and the following
|
|
|
|
// disclaimer in the documentation and/or other materials provided
|
|
|
|
// with the distribution.
|
|
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
|
|
// contributors may be used to endorse or promote products derived
|
|
|
|
// from this software without specific prior written permission.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
#ifndef V8_X64_LITHIUM_X64_H_
|
|
|
|
#define V8_X64_LITHIUM_X64_H_
|
|
|
|
|
|
|
|
#include "hydrogen.h"
|
|
|
|
#include "lithium-allocator.h"
|
|
|
|
#include "safepoint-table.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
// Forward declarations.
|
|
|
|
class LCodeGen;
|
|
|
|
class LEnvironment;
|
|
|
|
class Translation;
|
|
|
|
|
|
|
|
class LInstruction: public ZoneObject {
|
|
|
|
public:
|
|
|
|
LInstruction() { }
|
|
|
|
virtual ~LInstruction() { }
|
|
|
|
|
2011-01-07 09:47:16 +00:00
|
|
|
virtual void PrintTo(StringStream* stream) const { UNIMPLEMENTED(); }
|
|
|
|
virtual void PrintDataTo(StringStream* stream) const { }
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
// Predicates should be generated by macro as in lithium-ia32.h.
|
|
|
|
virtual bool IsLabel() const {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
virtual bool IsOsrEntry() const {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-07 09:47:16 +00:00
|
|
|
void set_environment(LEnvironment* env) { environment_.set(env); }
|
|
|
|
LEnvironment* environment() const { return environment_.get(); }
|
|
|
|
bool HasEnvironment() const { return environment_.is_set(); }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2011-01-07 09:47:16 +00:00
|
|
|
void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
|
|
|
|
LPointerMap* pointer_map() const { return pointer_map_.get(); }
|
|
|
|
bool HasPointerMap() const { return pointer_map_.is_set(); }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2011-01-07 09:47:16 +00:00
|
|
|
void set_result(LOperand* operand) { result_.set(operand); }
|
|
|
|
LOperand* result() const { return result_.get(); }
|
|
|
|
bool HasResult() const { return result_.is_set(); }
|
|
|
|
|
|
|
|
void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
|
|
|
|
HValue* hydrogen_value() const { return hydrogen_value_; }
|
|
|
|
|
|
|
|
void set_deoptimization_environment(LEnvironment* env) {
|
|
|
|
deoptimization_environment_.set(env);
|
|
|
|
}
|
|
|
|
LEnvironment* deoptimization_environment() const {
|
|
|
|
return deoptimization_environment_.get();
|
|
|
|
}
|
|
|
|
bool HasDeoptimizationEnvironment() const {
|
|
|
|
return deoptimization_environment_.is_set();
|
|
|
|
}
|
2011-01-05 12:31:31 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
SetOncePointer<LEnvironment> environment_;
|
|
|
|
SetOncePointer<LPointerMap> pointer_map_;
|
|
|
|
SetOncePointer<LOperand> result_;
|
|
|
|
HValue* hydrogen_value_;
|
|
|
|
SetOncePointer<LEnvironment> deoptimization_environment_;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class LParallelMove : public ZoneObject {
|
|
|
|
public:
|
2011-01-05 12:31:31 +00:00
|
|
|
LParallelMove() : move_operands_(4) { }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
void AddMove(LOperand* from, LOperand* to) {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
}
|
|
|
|
|
|
|
|
const ZoneList<LMoveOperands>* move_operands() const {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return NULL;
|
|
|
|
}
|
2011-01-05 12:31:31 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
ZoneList<LMoveOperands> move_operands_;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class LGap: public LInstruction {
|
|
|
|
public:
|
|
|
|
explicit LGap(HBasicBlock* block) { }
|
|
|
|
|
|
|
|
HBasicBlock* block() const {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum InnerPosition {
|
|
|
|
BEFORE,
|
|
|
|
START,
|
|
|
|
END,
|
|
|
|
AFTER,
|
|
|
|
FIRST_INNER_POSITION = BEFORE,
|
|
|
|
LAST_INNER_POSITION = AFTER
|
|
|
|
};
|
|
|
|
|
|
|
|
LParallelMove* GetOrCreateParallelMove(InnerPosition pos) {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LParallelMove* GetParallelMove(InnerPosition pos) {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return NULL;
|
|
|
|
}
|
2011-01-05 12:31:31 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
|
|
|
|
HBasicBlock* block_;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class LLabel: public LGap {
|
|
|
|
public:
|
|
|
|
explicit LLabel(HBasicBlock* block) : LGap(block) { }
|
2011-01-05 12:31:31 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
Label label_;
|
|
|
|
LLabel* replacement_;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class LOsrEntry: public LInstruction {
|
|
|
|
public:
|
|
|
|
// Function could be generated by a macro as in lithium-ia32.h.
|
|
|
|
static LOsrEntry* cast(LInstruction* instr) {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOperand** SpilledRegisterArray() {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
LOperand** SpilledDoubleRegisterArray() {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MarkSpilledRegister(int allocation_index, LOperand* spill_operand) {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
}
|
|
|
|
void MarkSpilledDoubleRegister(int allocation_index,
|
|
|
|
LOperand* spill_operand) {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
}
|
2011-01-05 12:31:31 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
// Arrays of spill slot operands for registers with an assigned spill
|
|
|
|
// slot, i.e., that must also be restored to the spill slot on OSR entry.
|
|
|
|
// NULL if the register has no assigned spill slot. Indexed by allocation
|
|
|
|
// index.
|
|
|
|
LOperand* register_spills_[Register::kNumAllocatableRegisters];
|
|
|
|
LOperand* double_register_spills_[DoubleRegister::kNumAllocatableRegisters];
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class LPointerMap: public ZoneObject {
|
|
|
|
public:
|
2011-01-05 12:31:31 +00:00
|
|
|
explicit LPointerMap(int position)
|
|
|
|
: pointer_operands_(8), position_(position), lithium_position_(-1) { }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
int lithium_position() const {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RecordPointer(LOperand* op) { UNIMPLEMENTED(); }
|
2011-01-05 12:31:31 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
ZoneList<LOperand*> pointer_operands_;
|
|
|
|
int position_;
|
|
|
|
int lithium_position_;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-01-05 12:31:31 +00:00
|
|
|
class LEnvironment: public ZoneObject {
|
2010-12-07 11:31:57 +00:00
|
|
|
public:
|
2011-01-05 12:31:31 +00:00
|
|
|
LEnvironment(Handle<JSFunction> closure,
|
|
|
|
int ast_id,
|
|
|
|
int parameter_count,
|
|
|
|
int argument_count,
|
|
|
|
int value_count,
|
|
|
|
LEnvironment* outer)
|
|
|
|
: closure_(closure),
|
|
|
|
arguments_stack_height_(argument_count),
|
|
|
|
deoptimization_index_(Safepoint::kNoDeoptimizationIndex),
|
|
|
|
translation_index_(-1),
|
|
|
|
ast_id_(ast_id),
|
|
|
|
parameter_count_(parameter_count),
|
|
|
|
values_(value_count),
|
|
|
|
representations_(value_count),
|
|
|
|
spilled_registers_(NULL),
|
|
|
|
spilled_double_registers_(NULL),
|
|
|
|
outer_(outer) {
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
2011-01-05 12:31:31 +00:00
|
|
|
Handle<JSFunction> closure() const { return closure_; }
|
|
|
|
int arguments_stack_height() const { return arguments_stack_height_; }
|
|
|
|
int deoptimization_index() const { return deoptimization_index_; }
|
|
|
|
int translation_index() const { return translation_index_; }
|
|
|
|
int ast_id() const { return ast_id_; }
|
|
|
|
int parameter_count() const { return parameter_count_; }
|
|
|
|
const ZoneList<LOperand*>* values() const { return &values_; }
|
|
|
|
LEnvironment* outer() const { return outer_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
Handle<JSFunction> closure_;
|
|
|
|
int arguments_stack_height_;
|
|
|
|
int deoptimization_index_;
|
|
|
|
int translation_index_;
|
|
|
|
int ast_id_;
|
|
|
|
int parameter_count_;
|
|
|
|
ZoneList<LOperand*> values_;
|
|
|
|
ZoneList<Representation> representations_;
|
|
|
|
|
|
|
|
// Allocation index indexed arrays of spill slot operands for registers
|
|
|
|
// that are also in spill slots at an OSR entry. NULL for environments
|
|
|
|
// that do not correspond to an OSR entry.
|
|
|
|
LOperand** spilled_registers_;
|
|
|
|
LOperand** spilled_double_registers_;
|
|
|
|
|
|
|
|
LEnvironment* outer_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class LChunkBuilder;
|
|
|
|
class LChunk: public ZoneObject {
|
|
|
|
public:
|
|
|
|
explicit LChunk(HGraph* graph)
|
|
|
|
: spill_slot_count_(0),
|
|
|
|
graph_(graph),
|
|
|
|
instructions_(32),
|
|
|
|
pointer_maps_(8),
|
|
|
|
inlined_closures_(1) { }
|
|
|
|
|
|
|
|
int spill_slot_count() const { return spill_slot_count_; }
|
|
|
|
HGraph* graph() const { return graph_; }
|
|
|
|
const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
|
|
|
|
const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
|
|
|
|
const ZoneList<Handle<JSFunction> >* inlined_closures() const {
|
|
|
|
return &inlined_closures_;
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LOperand* GetNextSpillSlot(bool double_slot) {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LConstantOperand* DefineConstantOperand(HConstant* constant) {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LLabel* GetLabel(int block_id) const {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetParameterStackSlot(int index) const {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AddGapMove(int index, LOperand* from, LOperand* to) { UNIMPLEMENTED(); }
|
|
|
|
|
|
|
|
LGap* GetGapAt(int index) const {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsGapAt(int index) const {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int NearestGapPos(int index) const {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MarkEmptyBlocks() { UNIMPLEMENTED(); }
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2011-01-05 12:31:31 +00:00
|
|
|
void Verify() { }
|
2010-12-07 11:31:57 +00:00
|
|
|
#endif
|
2011-01-05 12:31:31 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
int spill_slot_count_;
|
|
|
|
HGraph* const graph_;
|
|
|
|
ZoneList<LInstruction*> instructions_;
|
|
|
|
ZoneList<LPointerMap*> pointer_maps_;
|
|
|
|
ZoneList<Handle<JSFunction> > inlined_closures_;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class LChunkBuilder BASE_EMBEDDED {
|
|
|
|
public:
|
2011-01-05 12:31:31 +00:00
|
|
|
LChunkBuilder(HGraph* graph, LAllocator* allocator)
|
|
|
|
: chunk_(NULL),
|
|
|
|
graph_(graph),
|
|
|
|
status_(UNUSED),
|
|
|
|
current_instruction_(NULL),
|
|
|
|
current_block_(NULL),
|
|
|
|
next_block_(NULL),
|
|
|
|
argument_count_(0),
|
|
|
|
allocator_(allocator),
|
|
|
|
position_(RelocInfo::kNoPosition),
|
|
|
|
instructions_pending_deoptimization_environment_(NULL),
|
|
|
|
pending_deoptimization_ast_id_(AstNode::kNoNumber) { }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
// Build the sequence for the graph.
|
2011-01-05 12:31:31 +00:00
|
|
|
LChunk* Build();
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
// Declare methods that deal with the individual node types.
|
|
|
|
#define DECLARE_DO(type) LInstruction* Do##type(H##type* node) { \
|
|
|
|
UNIMPLEMENTED(); \
|
|
|
|
return NULL; \
|
|
|
|
}
|
|
|
|
HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
|
|
|
|
#undef DECLARE_DO
|
|
|
|
|
2011-01-05 12:31:31 +00:00
|
|
|
private:
|
|
|
|
enum Status {
|
|
|
|
UNUSED,
|
|
|
|
BUILDING,
|
|
|
|
DONE,
|
|
|
|
ABORTED
|
|
|
|
};
|
|
|
|
|
|
|
|
LChunk* chunk() const { return chunk_; }
|
|
|
|
HGraph* graph() const { return graph_; }
|
|
|
|
|
|
|
|
bool is_unused() const { return status_ == UNUSED; }
|
|
|
|
bool is_building() const { return status_ == BUILDING; }
|
|
|
|
bool is_done() const { return status_ == DONE; }
|
|
|
|
bool is_aborted() const { return status_ == ABORTED; }
|
|
|
|
|
|
|
|
void Abort(const char* format, ...);
|
|
|
|
|
|
|
|
void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block);
|
|
|
|
|
|
|
|
LChunk* chunk_;
|
|
|
|
HGraph* const graph_;
|
|
|
|
Status status_;
|
|
|
|
HInstruction* current_instruction_;
|
|
|
|
HBasicBlock* current_block_;
|
|
|
|
HBasicBlock* next_block_;
|
|
|
|
int argument_count_;
|
|
|
|
LAllocator* allocator_;
|
|
|
|
int position_;
|
|
|
|
LInstruction* instructions_pending_deoptimization_environment_;
|
|
|
|
int pending_deoptimization_ast_id_;
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
} } // namespace v8::internal
|
|
|
|
|
|
|
|
#endif // V8_X64_LITHIUM_X64_H_
|