mirror of https://github.com/lukechilds/node.git
Ryan Dahl
15 years ago
176 changed files with 8628 additions and 6128 deletions
@ -1,263 +0,0 @@ |
|||||
// Copyright (c) 1994-2006 Sun Microsystems Inc.
|
|
||||
// All Rights Reserved.
|
|
||||
//
|
|
||||
// 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.
|
|
||||
//
|
|
||||
// - Redistribution 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 Sun Microsystems or the names of 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.
|
|
||||
|
|
||||
// The original source code covered by the above license above has been modified
|
|
||||
// significantly by Google Inc.
|
|
||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
|
||||
|
|
||||
#ifndef V8_ARM_ASSEMBLER_THUMB2_INL_H_ |
|
||||
#define V8_ARM_ASSEMBLER_THUMB2_INL_H_ |
|
||||
|
|
||||
#include "arm/assembler-thumb2.h" |
|
||||
#include "cpu.h" |
|
||||
|
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
Condition NegateCondition(Condition cc) { |
|
||||
ASSERT(cc != al); |
|
||||
return static_cast<Condition>(cc ^ ne); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void RelocInfo::apply(intptr_t delta) { |
|
||||
if (RelocInfo::IsInternalReference(rmode_)) { |
|
||||
// absolute code pointer inside code object moves with the code object.
|
|
||||
int32_t* p = reinterpret_cast<int32_t*>(pc_); |
|
||||
*p += delta; // relocate entry
|
|
||||
} |
|
||||
// We do not use pc relative addressing on ARM, so there is
|
|
||||
// nothing else to do.
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
Address RelocInfo::target_address() { |
|
||||
ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); |
|
||||
return Assembler::target_address_at(pc_); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Address RelocInfo::target_address_address() { |
|
||||
ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); |
|
||||
return reinterpret_cast<Address>(Assembler::target_address_address_at(pc_)); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void RelocInfo::set_target_address(Address target) { |
|
||||
ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); |
|
||||
Assembler::set_target_address_at(pc_, target); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Object* RelocInfo::target_object() { |
|
||||
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
|
||||
return Memory::Object_at(Assembler::target_address_address_at(pc_)); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { |
|
||||
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
|
||||
return Memory::Object_Handle_at(Assembler::target_address_address_at(pc_)); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Object** RelocInfo::target_object_address() { |
|
||||
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
|
||||
return reinterpret_cast<Object**>(Assembler::target_address_address_at(pc_)); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void RelocInfo::set_target_object(Object* target) { |
|
||||
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
|
||||
Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target)); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Address* RelocInfo::target_reference_address() { |
|
||||
ASSERT(rmode_ == EXTERNAL_REFERENCE); |
|
||||
return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_)); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Address RelocInfo::call_address() { |
|
||||
ASSERT(IsPatchedReturnSequence()); |
|
||||
// The 2 instructions offset assumes patched return sequence.
|
|
||||
ASSERT(IsJSReturn(rmode())); |
|
||||
return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void RelocInfo::set_call_address(Address target) { |
|
||||
ASSERT(IsPatchedReturnSequence()); |
|
||||
// The 2 instructions offset assumes patched return sequence.
|
|
||||
ASSERT(IsJSReturn(rmode())); |
|
||||
Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Object* RelocInfo::call_object() { |
|
||||
return *call_object_address(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Object** RelocInfo::call_object_address() { |
|
||||
ASSERT(IsPatchedReturnSequence()); |
|
||||
// The 2 instructions offset assumes patched return sequence.
|
|
||||
ASSERT(IsJSReturn(rmode())); |
|
||||
return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void RelocInfo::set_call_object(Object* target) { |
|
||||
*call_object_address() = target; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
bool RelocInfo::IsPatchedReturnSequence() { |
|
||||
// On ARM a "call instruction" is actually two instructions.
|
|
||||
// mov lr, pc
|
|
||||
// ldr pc, [pc, #XXX]
|
|
||||
return (Assembler::instr_at(pc_) == kMovLrPc) |
|
||||
&& ((Assembler::instr_at(pc_ + Assembler::kInstrSize) & kLdrPCPattern) |
|
||||
== kLdrPCPattern); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { |
|
||||
rm_ = no_reg; |
|
||||
imm32_ = immediate; |
|
||||
rmode_ = rmode; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Operand::Operand(const char* s) { |
|
||||
rm_ = no_reg; |
|
||||
imm32_ = reinterpret_cast<int32_t>(s); |
|
||||
rmode_ = RelocInfo::EMBEDDED_STRING; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Operand::Operand(const ExternalReference& f) { |
|
||||
rm_ = no_reg; |
|
||||
imm32_ = reinterpret_cast<int32_t>(f.address()); |
|
||||
rmode_ = RelocInfo::EXTERNAL_REFERENCE; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Operand::Operand(Smi* value) { |
|
||||
rm_ = no_reg; |
|
||||
imm32_ = reinterpret_cast<intptr_t>(value); |
|
||||
rmode_ = RelocInfo::NONE; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Operand::Operand(Register rm) { |
|
||||
rm_ = rm; |
|
||||
rs_ = no_reg; |
|
||||
shift_op_ = LSL; |
|
||||
shift_imm_ = 0; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
bool Operand::is_reg() const { |
|
||||
return rm_.is_valid() && |
|
||||
rs_.is(no_reg) && |
|
||||
shift_op_ == LSL && |
|
||||
shift_imm_ == 0; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void Assembler::CheckBuffer() { |
|
||||
if (buffer_space() <= kGap) { |
|
||||
GrowBuffer(); |
|
||||
} |
|
||||
if (pc_offset() >= next_buffer_check_) { |
|
||||
CheckConstPool(false, true); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void Assembler::emit(Instr x) { |
|
||||
CheckBuffer(); |
|
||||
*reinterpret_cast<Instr*>(pc_) = x; |
|
||||
pc_ += kInstrSize; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Address Assembler::target_address_address_at(Address pc) { |
|
||||
Address target_pc = pc; |
|
||||
Instr instr = Memory::int32_at(target_pc); |
|
||||
// If we have a bx instruction, the instruction before the bx is
|
|
||||
// what we need to patch.
|
|
||||
static const int32_t kBxInstMask = 0x0ffffff0; |
|
||||
static const int32_t kBxInstPattern = 0x012fff10; |
|
||||
if ((instr & kBxInstMask) == kBxInstPattern) { |
|
||||
target_pc -= kInstrSize; |
|
||||
instr = Memory::int32_at(target_pc); |
|
||||
} |
|
||||
// Verify that the instruction to patch is a
|
|
||||
// ldr<cond> <Rd>, [pc +/- offset_12].
|
|
||||
ASSERT((instr & 0x0f7f0000) == 0x051f0000); |
|
||||
int offset = instr & 0xfff; // offset_12 is unsigned
|
|
||||
if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign
|
|
||||
// Verify that the constant pool comes after the instruction referencing it.
|
|
||||
ASSERT(offset >= -4); |
|
||||
return target_pc + offset + 8; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Address Assembler::target_address_at(Address pc) { |
|
||||
return Memory::Address_at(target_address_address_at(pc)); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void Assembler::set_target_at(Address constant_pool_entry, |
|
||||
Address target) { |
|
||||
Memory::Address_at(constant_pool_entry) = target; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void Assembler::set_target_address_at(Address pc, Address target) { |
|
||||
Memory::Address_at(target_address_address_at(pc)) = target; |
|
||||
// Intuitively, we would think it is necessary to flush the instruction cache
|
|
||||
// after patching a target address in the code as follows:
|
|
||||
// CPU::FlushICache(pc, sizeof(target));
|
|
||||
// However, on ARM, no instruction was actually patched by the assignment
|
|
||||
// above; the target address is not part of an instruction, it is patched in
|
|
||||
// the constant pool and is read via a data access; the instruction accessing
|
|
||||
// this address in the constant pool remains unchanged.
|
|
||||
} |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
||||
|
|
||||
#endif // V8_ARM_ASSEMBLER_THUMB2_INL_H_
|
|
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,53 @@ |
|||||
|
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
|
// 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_VIRTUAL_FRAME_ARM_INL_H_ |
||||
|
#define V8_VIRTUAL_FRAME_ARM_INL_H_ |
||||
|
|
||||
|
#include "assembler-arm.h" |
||||
|
#include "virtual-frame-arm.h" |
||||
|
|
||||
|
namespace v8 { |
||||
|
namespace internal { |
||||
|
|
||||
|
// These VirtualFrame methods should actually be in a virtual-frame-arm-inl.h
|
||||
|
// file if such a thing existed.
|
||||
|
MemOperand VirtualFrame::ParameterAt(int index) { |
||||
|
// Index -1 corresponds to the receiver.
|
||||
|
ASSERT(-1 <= index); // -1 is the receiver.
|
||||
|
ASSERT(index <= parameter_count()); |
||||
|
return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize); |
||||
|
} |
||||
|
|
||||
|
// The receiver frame slot.
|
||||
|
MemOperand VirtualFrame::Receiver() { |
||||
|
return ParameterAt(-1); |
||||
|
} |
||||
|
|
||||
|
} } // namespace v8::internal
|
||||
|
|
||||
|
#endif // V8_VIRTUAL_FRAME_ARM_INL_H_
|
@ -0,0 +1,79 @@ |
|||||
|
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
|
// 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.
|
||||
|
|
||||
|
#include "v8.h" |
||||
|
|
||||
|
#include "ast.h" |
||||
|
|
||||
|
namespace v8 { |
||||
|
namespace internal { |
||||
|
|
||||
|
BreakableStatement::BreakableStatement(ZoneStringList* labels, Type type) |
||||
|
: labels_(labels), type_(type) { |
||||
|
ASSERT(labels == NULL || labels->length() > 0); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
SwitchStatement::SwitchStatement(ZoneStringList* labels) |
||||
|
: BreakableStatement(labels, TARGET_FOR_ANONYMOUS), |
||||
|
tag_(NULL), cases_(NULL) { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
IterationStatement::IterationStatement(ZoneStringList* labels) |
||||
|
: BreakableStatement(labels, TARGET_FOR_ANONYMOUS), body_(NULL) { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
Block::Block(ZoneStringList* labels, int capacity, bool is_initializer_block) |
||||
|
: BreakableStatement(labels, TARGET_FOR_NAMED_ONLY), |
||||
|
statements_(capacity), |
||||
|
is_initializer_block_(is_initializer_block) { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
ForStatement::ForStatement(ZoneStringList* labels) |
||||
|
: IterationStatement(labels), |
||||
|
init_(NULL), |
||||
|
cond_(NULL), |
||||
|
next_(NULL), |
||||
|
may_have_function_literal_(true), |
||||
|
loop_variable_(NULL), |
||||
|
peel_this_loop_(false) { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
ForInStatement::ForInStatement(ZoneStringList* labels) |
||||
|
: IterationStatement(labels), each_(NULL), enumerable_(NULL) { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
DoWhileStatement::DoWhileStatement(ZoneStringList* labels) |
||||
|
: IterationStatement(labels), cond_(NULL), condition_position_(-1) { |
||||
|
} |
||||
|
|
||||
|
} } // namespace v8::internal
|
File diff suppressed because it is too large
@ -0,0 +1,242 @@ |
|||||
|
// Copyright 2008 the V8 project authors. All rights reserved.
|
||||
|
// 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_JUMP_TARGET_HEAVY_H_ |
||||
|
#define V8_JUMP_TARGET_HEAVY_H_ |
||||
|
|
||||
|
#include "macro-assembler.h" |
||||
|
#include "zone-inl.h" |
||||
|
|
||||
|
namespace v8 { |
||||
|
namespace internal { |
||||
|
|
||||
|
// Forward declarations.
|
||||
|
class FrameElement; |
||||
|
class Result; |
||||
|
class VirtualFrame; |
||||
|
|
||||
|
// -------------------------------------------------------------------------
|
||||
|
// Jump targets
|
||||
|
//
|
||||
|
// A jump target is an abstraction of a basic-block entry in generated
|
||||
|
// code. It collects all the virtual frames reaching the block by
|
||||
|
// forward jumps and pairs them with labels for the merge code along
|
||||
|
// all forward-reaching paths. When bound, an expected frame for the
|
||||
|
// block is determined and code is generated to merge to the expected
|
||||
|
// frame. For backward jumps, the merge code is generated at the edge
|
||||
|
// leaving the predecessor block.
|
||||
|
//
|
||||
|
// A jump target must have been reached via control flow (either by
|
||||
|
// jumping, branching, or falling through) at the time it is bound.
|
||||
|
// In particular, this means that at least one of the control-flow
|
||||
|
// graph edges reaching the target must be a forward edge.
|
||||
|
|
||||
|
class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
|
||||
|
public: |
||||
|
// Forward-only jump targets can only be reached by forward CFG edges.
|
||||
|
enum Directionality { FORWARD_ONLY, BIDIRECTIONAL }; |
||||
|
|
||||
|
// Construct a jump target used to generate code and to provide
|
||||
|
// access to a current frame.
|
||||
|
explicit JumpTarget(Directionality direction) |
||||
|
: direction_(direction), |
||||
|
reaching_frames_(0), |
||||
|
merge_labels_(0), |
||||
|
entry_frame_(NULL) { |
||||
|
} |
||||
|
|
||||
|
// Construct a jump target.
|
||||
|
JumpTarget() |
||||
|
: direction_(FORWARD_ONLY), |
||||
|
reaching_frames_(0), |
||||
|
merge_labels_(0), |
||||
|
entry_frame_(NULL) { |
||||
|
} |
||||
|
|
||||
|
virtual ~JumpTarget() {} |
||||
|
|
||||
|
// Set the direction of the jump target.
|
||||
|
virtual void set_direction(Directionality direction) { |
||||
|
direction_ = direction; |
||||
|
} |
||||
|
|
||||
|
// Treat the jump target as a fresh one. The state is reset.
|
||||
|
void Unuse(); |
||||
|
|
||||
|
inline CodeGenerator* cgen(); |
||||
|
|
||||
|
Label* entry_label() { return &entry_label_; } |
||||
|
|
||||
|
VirtualFrame* entry_frame() const { return entry_frame_; } |
||||
|
void set_entry_frame(VirtualFrame* frame) { |
||||
|
entry_frame_ = frame; |
||||
|
} |
||||
|
|
||||
|
// Predicates testing the state of the encapsulated label.
|
||||
|
bool is_bound() const { return entry_label_.is_bound(); } |
||||
|
bool is_linked() const { |
||||
|
return !is_bound() && !reaching_frames_.is_empty(); |
||||
|
} |
||||
|
bool is_unused() const { |
||||
|
// This is !is_bound() && !is_linked().
|
||||
|
return !is_bound() && reaching_frames_.is_empty(); |
||||
|
} |
||||
|
|
||||
|
// Emit a jump to the target. There must be a current frame at the
|
||||
|
// jump and there will be no current frame after the jump.
|
||||
|
virtual void Jump(); |
||||
|
virtual void Jump(Result* arg); |
||||
|
|
||||
|
// Emit a conditional branch to the target. There must be a current
|
||||
|
// frame at the branch. The current frame will fall through to the
|
||||
|
// code after the branch. The arg is a result that is live both at
|
||||
|
// the target and the fall-through.
|
||||
|
virtual void Branch(Condition cc, Hint hint = no_hint); |
||||
|
virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint); |
||||
|
virtual void Branch(Condition cc, |
||||
|
Result* arg0, |
||||
|
Result* arg1, |
||||
|
Hint hint = no_hint); |
||||
|
|
||||
|
// Bind a jump target. If there is no current frame at the binding
|
||||
|
// site, there must be at least one frame reaching via a forward
|
||||
|
// jump.
|
||||
|
virtual void Bind(); |
||||
|
virtual void Bind(Result* arg); |
||||
|
virtual void Bind(Result* arg0, Result* arg1); |
||||
|
|
||||
|
// Emit a call to a jump target. There must be a current frame at
|
||||
|
// the call. The frame at the target is the same as the current
|
||||
|
// frame except for an extra return address on top of it. The frame
|
||||
|
// after the call is the same as the frame before the call.
|
||||
|
void Call(); |
||||
|
|
||||
|
static void set_compiling_deferred_code(bool flag) { |
||||
|
compiling_deferred_code_ = flag; |
||||
|
} |
||||
|
|
||||
|
protected: |
||||
|
// Directionality flag set at initialization time.
|
||||
|
Directionality direction_; |
||||
|
|
||||
|
// A list of frames reaching this block via forward jumps.
|
||||
|
ZoneList<VirtualFrame*> reaching_frames_; |
||||
|
|
||||
|
// A parallel list of labels for merge code.
|
||||
|
ZoneList<Label> merge_labels_; |
||||
|
|
||||
|
// The frame used on entry to the block and expected at backward
|
||||
|
// jumps to the block. Set when the jump target is bound, but may
|
||||
|
// or may not be set for forward-only blocks.
|
||||
|
VirtualFrame* entry_frame_; |
||||
|
|
||||
|
// The actual entry label of the block.
|
||||
|
Label entry_label_; |
||||
|
|
||||
|
// Implementations of Jump, Branch, and Bind with all arguments and
|
||||
|
// return values using the virtual frame.
|
||||
|
void DoJump(); |
||||
|
void DoBranch(Condition cc, Hint hint); |
||||
|
void DoBind(); |
||||
|
|
||||
|
private: |
||||
|
static bool compiling_deferred_code_; |
||||
|
|
||||
|
// Add a virtual frame reaching this labeled block via a forward jump,
|
||||
|
// and a corresponding merge code label.
|
||||
|
void AddReachingFrame(VirtualFrame* frame); |
||||
|
|
||||
|
// Perform initialization required during entry frame computation
|
||||
|
// after setting the virtual frame element at index in frame to be
|
||||
|
// target.
|
||||
|
inline void InitializeEntryElement(int index, FrameElement* target); |
||||
|
|
||||
|
// Compute a frame to use for entry to this block.
|
||||
|
void ComputeEntryFrame(); |
||||
|
|
||||
|
DISALLOW_COPY_AND_ASSIGN(JumpTarget); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
// -------------------------------------------------------------------------
|
||||
|
// Break targets
|
||||
|
//
|
||||
|
// A break target is a jump target that can be used to break out of a
|
||||
|
// statement that keeps extra state on the stack (eg, for/in or
|
||||
|
// try/finally). They know the expected stack height at the target
|
||||
|
// and will drop state from nested statements as part of merging.
|
||||
|
//
|
||||
|
// Break targets are used for return, break, and continue targets.
|
||||
|
|
||||
|
class BreakTarget : public JumpTarget { |
||||
|
public: |
||||
|
// Construct a break target.
|
||||
|
BreakTarget() {} |
||||
|
|
||||
|
virtual ~BreakTarget() {} |
||||
|
|
||||
|
// Set the direction of the break target.
|
||||
|
virtual void set_direction(Directionality direction); |
||||
|
|
||||
|
// Copy the state of this break target to the destination. The
|
||||
|
// lists of forward-reaching frames and merge-point labels are
|
||||
|
// copied. All virtual frame pointers are copied, not the
|
||||
|
// pointed-to frames. The previous state of the destination is
|
||||
|
// overwritten, without deallocating pointed-to virtual frames.
|
||||
|
void CopyTo(BreakTarget* destination); |
||||
|
|
||||
|
// Emit a jump to the target. There must be a current frame at the
|
||||
|
// jump and there will be no current frame after the jump.
|
||||
|
virtual void Jump(); |
||||
|
virtual void Jump(Result* arg); |
||||
|
|
||||
|
// Emit a conditional branch to the target. There must be a current
|
||||
|
// frame at the branch. The current frame will fall through to the
|
||||
|
// code after the branch.
|
||||
|
virtual void Branch(Condition cc, Hint hint = no_hint); |
||||
|
virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint); |
||||
|
|
||||
|
// Bind a break target. If there is no current frame at the binding
|
||||
|
// site, there must be at least one frame reaching via a forward
|
||||
|
// jump.
|
||||
|
virtual void Bind(); |
||||
|
virtual void Bind(Result* arg); |
||||
|
|
||||
|
// Setter for expected height.
|
||||
|
void set_expected_height(int expected) { expected_height_ = expected; } |
||||
|
|
||||
|
private: |
||||
|
// The expected height of the expression stack where the target will
|
||||
|
// be bound, statically known at initialization time.
|
||||
|
int expected_height_; |
||||
|
|
||||
|
DISALLOW_COPY_AND_ASSIGN(BreakTarget); |
||||
|
}; |
||||
|
|
||||
|
} } // namespace v8::internal
|
||||
|
|
||||
|
#endif // V8_JUMP_TARGET_HEAVY_H_
|
@ -0,0 +1,187 @@ |
|||||
|
// Copyright 2008 the V8 project authors. All rights reserved.
|
||||
|
// 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_JUMP_TARGET_LIGHT_H_ |
||||
|
#define V8_JUMP_TARGET_LIGHT_H_ |
||||
|
|
||||
|
#include "macro-assembler.h" |
||||
|
#include "zone-inl.h" |
||||
|
#include "virtual-frame.h" |
||||
|
|
||||
|
namespace v8 { |
||||
|
namespace internal { |
||||
|
|
||||
|
// Forward declarations.
|
||||
|
class FrameElement; |
||||
|
class Result; |
||||
|
|
||||
|
// -------------------------------------------------------------------------
|
||||
|
// Jump targets
|
||||
|
//
|
||||
|
// A jump target is an abstraction of a basic-block entry in generated
|
||||
|
// code. It collects all the virtual frames reaching the block by
|
||||
|
// forward jumps and pairs them with labels for the merge code along
|
||||
|
// all forward-reaching paths. When bound, an expected frame for the
|
||||
|
// block is determined and code is generated to merge to the expected
|
||||
|
// frame. For backward jumps, the merge code is generated at the edge
|
||||
|
// leaving the predecessor block.
|
||||
|
//
|
||||
|
// A jump target must have been reached via control flow (either by
|
||||
|
// jumping, branching, or falling through) at the time it is bound.
|
||||
|
// In particular, this means that at least one of the control-flow
|
||||
|
// graph edges reaching the target must be a forward edge.
|
||||
|
|
||||
|
class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
|
||||
|
public: |
||||
|
// Forward-only jump targets can only be reached by forward CFG edges.
|
||||
|
enum Directionality { FORWARD_ONLY, BIDIRECTIONAL }; |
||||
|
|
||||
|
// Construct a jump target.
|
||||
|
explicit inline JumpTarget(Directionality direction); |
||||
|
|
||||
|
inline JumpTarget(); |
||||
|
|
||||
|
virtual ~JumpTarget() {} |
||||
|
|
||||
|
void Unuse() { |
||||
|
entry_frame_set_ = false; |
||||
|
entry_label_.Unuse(); |
||||
|
} |
||||
|
|
||||
|
inline CodeGenerator* cgen(); |
||||
|
|
||||
|
const VirtualFrame* entry_frame() const { |
||||
|
return entry_frame_set_ ? &entry_frame_ : NULL; |
||||
|
} |
||||
|
|
||||
|
void set_entry_frame(VirtualFrame* frame) { |
||||
|
entry_frame_ = *frame; |
||||
|
entry_frame_set_ = true; |
||||
|
} |
||||
|
|
||||
|
// Predicates testing the state of the encapsulated label.
|
||||
|
bool is_bound() const { return entry_label_.is_bound(); } |
||||
|
bool is_linked() const { return entry_label_.is_linked(); } |
||||
|
bool is_unused() const { return entry_label_.is_unused(); } |
||||
|
|
||||
|
// Copy the state of this jump target to the destination.
|
||||
|
inline void CopyTo(JumpTarget* destination) { |
||||
|
*destination = *this; |
||||
|
} |
||||
|
|
||||
|
// Emit a jump to the target. There must be a current frame at the
|
||||
|
// jump and there will be no current frame after the jump.
|
||||
|
virtual void Jump(); |
||||
|
|
||||
|
// Emit a conditional branch to the target. There must be a current
|
||||
|
// frame at the branch. The current frame will fall through to the
|
||||
|
// code after the branch. The arg is a result that is live both at
|
||||
|
// the target and the fall-through.
|
||||
|
virtual void Branch(Condition cc, Hint hint = no_hint); |
||||
|
|
||||
|
// Bind a jump target. If there is no current frame at the binding
|
||||
|
// site, there must be at least one frame reaching via a forward
|
||||
|
// jump.
|
||||
|
virtual void Bind(); |
||||
|
|
||||
|
// Emit a call to a jump target. There must be a current frame at
|
||||
|
// the call. The frame at the target is the same as the current
|
||||
|
// frame except for an extra return address on top of it. The frame
|
||||
|
// after the call is the same as the frame before the call.
|
||||
|
void Call(); |
||||
|
|
||||
|
protected: |
||||
|
// Has an entry frame been found?
|
||||
|
bool entry_frame_set_; |
||||
|
|
||||
|
// The frame used on entry to the block and expected at backward
|
||||
|
// jumps to the block. Set the first time something branches to this
|
||||
|
// jump target.
|
||||
|
VirtualFrame entry_frame_; |
||||
|
|
||||
|
// The actual entry label of the block.
|
||||
|
Label entry_label_; |
||||
|
|
||||
|
// Implementations of Jump, Branch, and Bind with all arguments and
|
||||
|
// return values using the virtual frame.
|
||||
|
void DoJump(); |
||||
|
void DoBranch(Condition cc, Hint hint); |
||||
|
void DoBind(); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
// -------------------------------------------------------------------------
|
||||
|
// Break targets
|
||||
|
//
|
||||
|
// A break target is a jump target that can be used to break out of a
|
||||
|
// statement that keeps extra state on the stack (eg, for/in or
|
||||
|
// try/finally). They know the expected stack height at the target
|
||||
|
// and will drop state from nested statements as part of merging.
|
||||
|
//
|
||||
|
// Break targets are used for return, break, and continue targets.
|
||||
|
|
||||
|
class BreakTarget : public JumpTarget { |
||||
|
public: |
||||
|
// Construct a break target.
|
||||
|
inline BreakTarget(); |
||||
|
|
||||
|
virtual ~BreakTarget() {} |
||||
|
|
||||
|
// Copy the state of this jump target to the destination.
|
||||
|
inline void CopyTo(BreakTarget* destination) { |
||||
|
*destination = *this; |
||||
|
} |
||||
|
|
||||
|
// Emit a jump to the target. There must be a current frame at the
|
||||
|
// jump and there will be no current frame after the jump.
|
||||
|
virtual void Jump(); |
||||
|
|
||||
|
// Emit a conditional branch to the target. There must be a current
|
||||
|
// frame at the branch. The current frame will fall through to the
|
||||
|
// code after the branch.
|
||||
|
virtual void Branch(Condition cc, Hint hint = no_hint); |
||||
|
|
||||
|
// Bind a break target. If there is no current frame at the binding
|
||||
|
// site, there must be at least one frame reaching via a forward
|
||||
|
// jump.
|
||||
|
virtual void Bind(); |
||||
|
|
||||
|
// Setter for expected height.
|
||||
|
void set_expected_height(int expected) { expected_height_ = expected; } |
||||
|
|
||||
|
// Uses the current frame to set the expected height.
|
||||
|
void SetExpectedHeight(); |
||||
|
|
||||
|
private: |
||||
|
// The expected height of the expression stack where the target will
|
||||
|
// be bound, statically known at initialization time.
|
||||
|
int expected_height_; |
||||
|
}; |
||||
|
|
||||
|
} } // namespace v8::internal
|
||||
|
|
||||
|
#endif // V8_JUMP_TARGET_LIGHT_H_
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue