Split the virtual frame into heavy and light versions.
The heavy version is for x86 and x64. The light version is for ARM and MIPS. Remove the elements_ array from the virtual frame in the light version. More simplifications to come, followed by light register allocation. Review URL: http://codereview.chromium.org/1164002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4272 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
5b50fd70ef
commit
f5523ecc6a
@ -113,6 +113,8 @@ SOURCES = {
|
|||||||
"""),
|
"""),
|
||||||
'arch:arm': Split("""
|
'arch:arm': Split("""
|
||||||
fast-codegen.cc
|
fast-codegen.cc
|
||||||
|
jump-target-light.cc
|
||||||
|
virtual-frame-light.cc
|
||||||
arm/builtins-arm.cc
|
arm/builtins-arm.cc
|
||||||
arm/codegen-arm.cc
|
arm/codegen-arm.cc
|
||||||
arm/constants-arm.cc
|
arm/constants-arm.cc
|
||||||
@ -156,6 +158,8 @@ SOURCES = {
|
|||||||
mips/virtual-frame-mips.cc
|
mips/virtual-frame-mips.cc
|
||||||
"""),
|
"""),
|
||||||
'arch:ia32': Split("""
|
'arch:ia32': Split("""
|
||||||
|
jump-target-heavy.cc
|
||||||
|
virtual-frame-heavy.cc
|
||||||
ia32/assembler-ia32.cc
|
ia32/assembler-ia32.cc
|
||||||
ia32/builtins-ia32.cc
|
ia32/builtins-ia32.cc
|
||||||
ia32/codegen-ia32.cc
|
ia32/codegen-ia32.cc
|
||||||
@ -175,6 +179,8 @@ SOURCES = {
|
|||||||
"""),
|
"""),
|
||||||
'arch:x64': Split("""
|
'arch:x64': Split("""
|
||||||
fast-codegen.cc
|
fast-codegen.cc
|
||||||
|
jump-target-heavy.cc
|
||||||
|
virtual-frame-heavy.cc
|
||||||
x64/assembler-x64.cc
|
x64/assembler-x64.cc
|
||||||
x64/builtins-x64.cc
|
x64/builtins-x64.cc
|
||||||
x64/codegen-x64.cc
|
x64/codegen-x64.cc
|
||||||
|
@ -173,14 +173,7 @@ void BreakTarget::Jump() {
|
|||||||
|
|
||||||
|
|
||||||
void BreakTarget::Jump(Result* arg) {
|
void BreakTarget::Jump(Result* arg) {
|
||||||
// On ARM we do not currently emit merge code for jumps, so we need to do
|
UNIMPLEMENTED();
|
||||||
// it explicitly here. The only merging necessary is to drop extra
|
|
||||||
// statement state from the stack.
|
|
||||||
ASSERT(cgen()->has_valid_frame());
|
|
||||||
int count = cgen()->frame()->height() - expected_height_;
|
|
||||||
cgen()->frame()->Drop(count);
|
|
||||||
cgen()->frame()->Push(arg);
|
|
||||||
DoJump();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -209,27 +202,7 @@ void BreakTarget::Bind() {
|
|||||||
|
|
||||||
|
|
||||||
void BreakTarget::Bind(Result* arg) {
|
void BreakTarget::Bind(Result* arg) {
|
||||||
#ifdef DEBUG
|
UNIMPLEMENTED();
|
||||||
// All the forward-reaching frames should have been adjusted at the
|
|
||||||
// jumps to this target.
|
|
||||||
for (int i = 0; i < reaching_frames_.length(); i++) {
|
|
||||||
ASSERT(reaching_frames_[i] == NULL ||
|
|
||||||
reaching_frames_[i]->height() == expected_height_ + 1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// Drop leftover statement state from the frame before merging, even
|
|
||||||
// on the fall through. This is so we can bind the return target
|
|
||||||
// with state on the frame.
|
|
||||||
if (cgen()->has_valid_frame()) {
|
|
||||||
int count = cgen()->frame()->height() - expected_height_;
|
|
||||||
// On ARM we do not currently emit merge code at binding sites, so we need
|
|
||||||
// to do it explicitly here. The only merging necessary is to drop extra
|
|
||||||
// statement state from the stack.
|
|
||||||
cgen()->frame()->ForgetElements(count);
|
|
||||||
cgen()->frame()->Push(arg);
|
|
||||||
}
|
|
||||||
DoBind();
|
|
||||||
*arg = cgen()->frame()->Pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,16 +47,6 @@ void VirtualFrame::SyncElementByPushing(int index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::SyncRange(int begin, int end) {
|
|
||||||
// All elements are in memory on ARM (ie, synced).
|
|
||||||
#ifdef DEBUG
|
|
||||||
for (int i = begin; i <= end; i++) {
|
|
||||||
ASSERT(elements_[i].is_synced());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::MergeTo(VirtualFrame* expected) {
|
void VirtualFrame::MergeTo(VirtualFrame* expected) {
|
||||||
// ARM frames are currently always in memory.
|
// ARM frames are currently always in memory.
|
||||||
ASSERT(Equals(expected));
|
ASSERT(Equals(expected));
|
||||||
@ -270,12 +260,7 @@ void VirtualFrame::Drop(int count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Discard elements from the virtual frame and free any registers.
|
// Discard elements from the virtual frame and free any registers.
|
||||||
for (int i = 0; i < count; i++) {
|
element_count_ -= count;
|
||||||
FrameElement dropped = elements_.RemoveLast();
|
|
||||||
if (dropped.is_register()) {
|
|
||||||
Unuse(dropped.reg());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -288,14 +273,14 @@ Result VirtualFrame::Pop() {
|
|||||||
void VirtualFrame::EmitPop(Register reg) {
|
void VirtualFrame::EmitPop(Register reg) {
|
||||||
ASSERT(stack_pointer_ == element_count() - 1);
|
ASSERT(stack_pointer_ == element_count() - 1);
|
||||||
stack_pointer_--;
|
stack_pointer_--;
|
||||||
elements_.RemoveLast();
|
element_count_--;
|
||||||
__ pop(reg);
|
__ pop(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::EmitPush(Register reg) {
|
void VirtualFrame::EmitPush(Register reg) {
|
||||||
ASSERT(stack_pointer_ == element_count() - 1);
|
ASSERT(stack_pointer_ == element_count() - 1);
|
||||||
elements_.Add(FrameElement::MemoryElement(TypeInfo::Unknown()));
|
element_count_++;
|
||||||
stack_pointer_++;
|
stack_pointer_++;
|
||||||
__ push(reg);
|
__ push(reg);
|
||||||
}
|
}
|
||||||
|
@ -67,12 +67,8 @@ class VirtualFrame : public ZoneObject {
|
|||||||
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
|
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
|
||||||
MacroAssembler* masm() { return cgen()->masm(); }
|
MacroAssembler* masm() { return cgen()->masm(); }
|
||||||
|
|
||||||
// Create a duplicate of an existing valid frame element.
|
|
||||||
FrameElement CopyElementAt(int index,
|
|
||||||
TypeInfo info = TypeInfo::Unknown());
|
|
||||||
|
|
||||||
// The number of elements on the virtual frame.
|
// The number of elements on the virtual frame.
|
||||||
int element_count() { return elements_.length(); }
|
int element_count() { return element_count_; }
|
||||||
|
|
||||||
// The height of the virtual expression stack.
|
// The height of the virtual expression stack.
|
||||||
int height() {
|
int height() {
|
||||||
@ -115,7 +111,7 @@ class VirtualFrame : public ZoneObject {
|
|||||||
stack_pointer_ -= count;
|
stack_pointer_ -= count;
|
||||||
// On ARM, all elements are in memory, so there is no extra bookkeeping
|
// On ARM, all elements are in memory, so there is no extra bookkeeping
|
||||||
// (registers, copies, etc.) beyond dropping the elements.
|
// (registers, copies, etc.) beyond dropping the elements.
|
||||||
elements_.Rewind(stack_pointer_ + 1);
|
element_count_ -= count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forget count elements from the top of the frame and adjust the stack
|
// Forget count elements from the top of the frame and adjust the stack
|
||||||
@ -124,7 +120,7 @@ class VirtualFrame : public ZoneObject {
|
|||||||
void ForgetElements(int count);
|
void ForgetElements(int count);
|
||||||
|
|
||||||
// Spill all values from the frame to memory.
|
// Spill all values from the frame to memory.
|
||||||
void SpillAll();
|
inline void SpillAll();
|
||||||
|
|
||||||
// Spill all occurrences of a specific register from the frame.
|
// Spill all occurrences of a specific register from the frame.
|
||||||
void Spill(Register reg) {
|
void Spill(Register reg) {
|
||||||
@ -179,7 +175,7 @@ class VirtualFrame : public ZoneObject {
|
|||||||
// dropping all non-locals elements in the virtual frame. This
|
// dropping all non-locals elements in the virtual frame. This
|
||||||
// avoids generating unnecessary merge code when jumping to the
|
// avoids generating unnecessary merge code when jumping to the
|
||||||
// shared return site. Emits code for spills.
|
// shared return site. Emits code for spills.
|
||||||
void PrepareForReturn();
|
inline void PrepareForReturn();
|
||||||
|
|
||||||
// Number of local variables after when we use a loop for allocating.
|
// Number of local variables after when we use a loop for allocating.
|
||||||
static const int kLocalVarBound = 5;
|
static const int kLocalVarBound = 5;
|
||||||
@ -205,10 +201,6 @@ class VirtualFrame : public ZoneObject {
|
|||||||
SetElementAt(index, &temp);
|
SetElementAt(index, &temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushElementAt(int index) {
|
|
||||||
PushFrameSlotAt(element_count() - index - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A frame-allocated local as an assembly operand.
|
// A frame-allocated local as an assembly operand.
|
||||||
MemOperand LocalAt(int index) {
|
MemOperand LocalAt(int index) {
|
||||||
ASSERT(0 <= index);
|
ASSERT(0 <= index);
|
||||||
@ -216,11 +208,6 @@ class VirtualFrame : public ZoneObject {
|
|||||||
return MemOperand(fp, kLocal0Offset - index * kPointerSize);
|
return MemOperand(fp, kLocal0Offset - index * kPointerSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push a copy of the value of a local frame slot on top of the frame.
|
|
||||||
void PushLocalAt(int index) {
|
|
||||||
PushFrameSlotAt(local0_index() + index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push the value of a local frame slot on top of the frame and invalidate
|
// Push the value of a local frame slot on top of the frame and invalidate
|
||||||
// the local slot. The slot should be written to before trying to read
|
// the local slot. The slot should be written to before trying to read
|
||||||
// from it again.
|
// from it again.
|
||||||
@ -228,21 +215,12 @@ class VirtualFrame : public ZoneObject {
|
|||||||
TakeFrameSlotAt(local0_index() + index);
|
TakeFrameSlotAt(local0_index() + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the top value on the virtual frame into a local frame slot. The
|
|
||||||
// value is left in place on top of the frame.
|
|
||||||
void StoreToLocalAt(int index) {
|
|
||||||
StoreToFrameSlotAt(local0_index() + index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push the address of the receiver slot on the frame.
|
// Push the address of the receiver slot on the frame.
|
||||||
void PushReceiverSlotAddress();
|
void PushReceiverSlotAddress();
|
||||||
|
|
||||||
// The function frame slot.
|
// The function frame slot.
|
||||||
MemOperand Function() { return MemOperand(fp, kFunctionOffset); }
|
MemOperand Function() { return MemOperand(fp, kFunctionOffset); }
|
||||||
|
|
||||||
// Push the function on top of the frame.
|
|
||||||
void PushFunction() { PushFrameSlotAt(function_index()); }
|
|
||||||
|
|
||||||
// The context frame slot.
|
// The context frame slot.
|
||||||
MemOperand Context() { return MemOperand(fp, kContextOffset); }
|
MemOperand Context() { return MemOperand(fp, kContextOffset); }
|
||||||
|
|
||||||
@ -261,11 +239,6 @@ class VirtualFrame : public ZoneObject {
|
|||||||
return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize);
|
return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push a copy of the value of a parameter frame slot on top of the frame.
|
|
||||||
void PushParameterAt(int index) {
|
|
||||||
PushFrameSlotAt(param0_index() + index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push the value of a paramter frame slot on top of the frame and
|
// Push the value of a paramter frame slot on top of the frame and
|
||||||
// invalidate the parameter slot. The slot should be written to before
|
// invalidate the parameter slot. The slot should be written to before
|
||||||
// trying to read from it again.
|
// trying to read from it again.
|
||||||
@ -323,9 +296,6 @@ class VirtualFrame : public ZoneObject {
|
|||||||
// Drop one element.
|
// Drop one element.
|
||||||
void Drop() { Drop(1); }
|
void Drop() { Drop(1); }
|
||||||
|
|
||||||
// Duplicate the top element of the frame.
|
|
||||||
void Dup() { PushFrameSlotAt(element_count() - 1); }
|
|
||||||
|
|
||||||
// Pop an element from the top of the expression stack. Returns a
|
// Pop an element from the top of the expression stack. Returns a
|
||||||
// Result, which may be a constant or a register.
|
// Result, which may be a constant or a register.
|
||||||
Result Pop();
|
Result Pop();
|
||||||
@ -344,21 +314,9 @@ class VirtualFrame : public ZoneObject {
|
|||||||
void EmitPushMultiple(int count, int src_regs);
|
void EmitPushMultiple(int count, int src_regs);
|
||||||
|
|
||||||
// Push an element on the virtual frame.
|
// Push an element on the virtual frame.
|
||||||
inline void Push(Register reg, TypeInfo info = TypeInfo::Unknown());
|
|
||||||
inline void Push(Handle<Object> value);
|
inline void Push(Handle<Object> value);
|
||||||
inline void Push(Smi* value);
|
inline void Push(Smi* value);
|
||||||
|
|
||||||
// Pushing a result invalidates it (its contents become owned by the frame).
|
|
||||||
void Push(Result* result) {
|
|
||||||
if (result->is_register()) {
|
|
||||||
Push(result->reg());
|
|
||||||
} else {
|
|
||||||
ASSERT(result->is_constant());
|
|
||||||
Push(result->handle());
|
|
||||||
}
|
|
||||||
result->Unuse();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nip removes zero or more elements from immediately below the top
|
// Nip removes zero or more elements from immediately below the top
|
||||||
// of the frame, leaving the previous top-of-frame value on top of
|
// of the frame, leaving the previous top-of-frame value on top of
|
||||||
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
|
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
|
||||||
@ -375,7 +333,8 @@ class VirtualFrame : public ZoneObject {
|
|||||||
static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize;
|
static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize;
|
||||||
static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots.
|
static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots.
|
||||||
|
|
||||||
ZoneList<FrameElement> elements_;
|
// The number of elements on the stack frame.
|
||||||
|
int element_count_;
|
||||||
|
|
||||||
// The index of the element that is at the processor's stack pointer
|
// The index of the element that is at the processor's stack pointer
|
||||||
// (the sp register).
|
// (the sp register).
|
||||||
@ -449,19 +408,12 @@ class VirtualFrame : public ZoneObject {
|
|||||||
// Keep the element type as register or constant, and clear the dirty bit.
|
// Keep the element type as register or constant, and clear the dirty bit.
|
||||||
void SyncElementAt(int index);
|
void SyncElementAt(int index);
|
||||||
|
|
||||||
// Sync the range of elements in [begin, end] with memory.
|
|
||||||
void SyncRange(int begin, int end);
|
|
||||||
|
|
||||||
// Sync a single unsynced element that lies beneath or at the stack pointer.
|
// Sync a single unsynced element that lies beneath or at the stack pointer.
|
||||||
void SyncElementBelowStackPointer(int index);
|
void SyncElementBelowStackPointer(int index);
|
||||||
|
|
||||||
// Sync a single unsynced element that lies just above the stack pointer.
|
// Sync a single unsynced element that lies just above the stack pointer.
|
||||||
void SyncElementByPushing(int index);
|
void SyncElementByPushing(int index);
|
||||||
|
|
||||||
// Push a copy of a frame slot (typically a local or parameter) on top of
|
|
||||||
// the frame.
|
|
||||||
inline void PushFrameSlotAt(int index);
|
|
||||||
|
|
||||||
// Push a the value of a frame slot (typically a local or parameter) on
|
// Push a the value of a frame slot (typically a local or parameter) on
|
||||||
// top of the frame and invalidate the slot.
|
// top of the frame and invalidate the slot.
|
||||||
void TakeFrameSlotAt(int index);
|
void TakeFrameSlotAt(int index);
|
||||||
@ -505,9 +457,8 @@ class VirtualFrame : public ZoneObject {
|
|||||||
|
|
||||||
inline bool Equals(VirtualFrame* other);
|
inline bool Equals(VirtualFrame* other);
|
||||||
|
|
||||||
// Classes that need raw access to the elements_ array.
|
|
||||||
friend class DeferredCode;
|
|
||||||
friend class JumpTarget;
|
friend class JumpTarget;
|
||||||
|
friend class DeferredCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,38 +66,6 @@ Comment::~Comment() {
|
|||||||
CodeGenerator* CodeGeneratorScope::top_ = NULL;
|
CodeGenerator* CodeGeneratorScope::top_ = NULL;
|
||||||
|
|
||||||
|
|
||||||
DeferredCode::DeferredCode()
|
|
||||||
: masm_(CodeGeneratorScope::Current()->masm()),
|
|
||||||
statement_position_(masm_->current_statement_position()),
|
|
||||||
position_(masm_->current_position()) {
|
|
||||||
ASSERT(statement_position_ != RelocInfo::kNoPosition);
|
|
||||||
ASSERT(position_ != RelocInfo::kNoPosition);
|
|
||||||
|
|
||||||
CodeGeneratorScope::Current()->AddDeferred(this);
|
|
||||||
#ifdef DEBUG
|
|
||||||
comment_ = "";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Copy the register locations from the code generator's frame.
|
|
||||||
// These are the registers that will be spilled on entry to the
|
|
||||||
// deferred code and restored on exit.
|
|
||||||
VirtualFrame* frame = CodeGeneratorScope::Current()->frame();
|
|
||||||
int sp_offset = frame->fp_relative(frame->stack_pointer_);
|
|
||||||
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
|
|
||||||
int loc = frame->register_location(i);
|
|
||||||
if (loc == VirtualFrame::kIllegalIndex) {
|
|
||||||
registers_[i] = kIgnore;
|
|
||||||
} else if (frame->elements_[loc].is_synced()) {
|
|
||||||
// Needs to be restored on exit but not saved on entry.
|
|
||||||
registers_[i] = frame->fp_relative(loc) | kSyncedFlag;
|
|
||||||
} else {
|
|
||||||
int offset = frame->fp_relative(loc);
|
|
||||||
registers_[i] = (offset < sp_offset) ? kPush : offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CodeGenerator::ProcessDeferred() {
|
void CodeGenerator::ProcessDeferred() {
|
||||||
while (!deferred_.is_empty()) {
|
while (!deferred_.is_empty()) {
|
||||||
DeferredCode* code = deferred_.RemoveLast();
|
DeferredCode* code = deferred_.RemoveLast();
|
||||||
|
@ -138,7 +138,7 @@ class VirtualFrame: public ZoneObject {
|
|||||||
void ForgetElements(int count);
|
void ForgetElements(int count);
|
||||||
|
|
||||||
// Spill all values from the frame to memory.
|
// Spill all values from the frame to memory.
|
||||||
void SpillAll();
|
inline void SpillAll();
|
||||||
|
|
||||||
// Spill all occurrences of a specific register from the frame.
|
// Spill all occurrences of a specific register from the frame.
|
||||||
void Spill(Register reg) {
|
void Spill(Register reg) {
|
||||||
@ -199,7 +199,7 @@ class VirtualFrame: public ZoneObject {
|
|||||||
// Prepare for returning from the frame by spilling locals. This
|
// Prepare for returning from the frame by spilling locals. This
|
||||||
// avoids generating unnecessary merge code when jumping to the
|
// avoids generating unnecessary merge code when jumping to the
|
||||||
// shared return site. Emits code for spills.
|
// shared return site. Emits code for spills.
|
||||||
void PrepareForReturn();
|
inline void PrepareForReturn();
|
||||||
|
|
||||||
// Number of local variables after when we use a loop for allocating.
|
// Number of local variables after when we use a loop for allocating.
|
||||||
static const int kLocalVarBound = 10;
|
static const int kLocalVarBound = 10;
|
||||||
|
51
src/jump-target-heavy-inl.h
Normal file
51
src/jump-target-heavy-inl.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// 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_JUMP_TARGET_HEAVY_INL_H_
|
||||||
|
#define V8_JUMP_TARGET_HEAVY_INL_H_
|
||||||
|
|
||||||
|
#include "virtual-frame-inl.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
|
||||||
|
FrameElement* element = &entry_frame_->elements_[index];
|
||||||
|
element->clear_copied();
|
||||||
|
if (target->is_register()) {
|
||||||
|
entry_frame_->set_register_location(target->reg(), index);
|
||||||
|
} else if (target->is_copy()) {
|
||||||
|
entry_frame_->elements_[target->index()].set_copied();
|
||||||
|
}
|
||||||
|
if (direction_ == BIDIRECTIONAL && !target->is_copy()) {
|
||||||
|
element->set_type_info(TypeInfo::Unknown());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} } // namespace v8::internal
|
||||||
|
|
||||||
|
#endif // V8_JUMP_TARGET_HEAVY_INL_H_
|
363
src/jump-target-heavy.cc
Normal file
363
src/jump-target-heavy.cc
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
// 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 "codegen-inl.h"
|
||||||
|
#include "jump-target-inl.h"
|
||||||
|
#include "register-allocator-inl.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::Jump(Result* arg) {
|
||||||
|
ASSERT(cgen()->has_valid_frame());
|
||||||
|
|
||||||
|
cgen()->frame()->Push(arg);
|
||||||
|
DoJump();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
|
||||||
|
ASSERT(cgen()->has_valid_frame());
|
||||||
|
|
||||||
|
// We want to check that non-frame registers at the call site stay in
|
||||||
|
// the same registers on the fall-through branch.
|
||||||
|
#ifdef DEBUG
|
||||||
|
Result::Type arg_type = arg->type();
|
||||||
|
Register arg_reg = arg->is_register() ? arg->reg() : no_reg;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cgen()->frame()->Push(arg);
|
||||||
|
DoBranch(cc, hint);
|
||||||
|
*arg = cgen()->frame()->Pop();
|
||||||
|
|
||||||
|
ASSERT(arg->type() == arg_type);
|
||||||
|
ASSERT(!arg->is_register() || arg->reg().is(arg_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
|
||||||
|
ASSERT(cgen()->has_valid_frame());
|
||||||
|
|
||||||
|
// We want to check that non-frame registers at the call site stay in
|
||||||
|
// the same registers on the fall-through branch.
|
||||||
|
#ifdef DEBUG
|
||||||
|
Result::Type arg0_type = arg0->type();
|
||||||
|
Register arg0_reg = arg0->is_register() ? arg0->reg() : no_reg;
|
||||||
|
Result::Type arg1_type = arg1->type();
|
||||||
|
Register arg1_reg = arg1->is_register() ? arg1->reg() : no_reg;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cgen()->frame()->Push(arg0);
|
||||||
|
cgen()->frame()->Push(arg1);
|
||||||
|
DoBranch(cc, hint);
|
||||||
|
*arg1 = cgen()->frame()->Pop();
|
||||||
|
*arg0 = cgen()->frame()->Pop();
|
||||||
|
|
||||||
|
ASSERT(arg0->type() == arg0_type);
|
||||||
|
ASSERT(!arg0->is_register() || arg0->reg().is(arg0_reg));
|
||||||
|
ASSERT(arg1->type() == arg1_type);
|
||||||
|
ASSERT(!arg1->is_register() || arg1->reg().is(arg1_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
|
||||||
|
ASSERT(cgen()->has_valid_frame());
|
||||||
|
|
||||||
|
int count = cgen()->frame()->height() - expected_height_;
|
||||||
|
if (count > 0) {
|
||||||
|
// We negate and branch here rather than using DoBranch's negate
|
||||||
|
// and branch. This gives us a hook to remove statement state
|
||||||
|
// from the frame.
|
||||||
|
JumpTarget fall_through;
|
||||||
|
// Branch to fall through will not negate, because it is a
|
||||||
|
// forward-only target.
|
||||||
|
fall_through.Branch(NegateCondition(cc), NegateHint(hint));
|
||||||
|
Jump(arg); // May emit merge code here.
|
||||||
|
fall_through.Bind();
|
||||||
|
} else {
|
||||||
|
#ifdef DEBUG
|
||||||
|
Result::Type arg_type = arg->type();
|
||||||
|
Register arg_reg = arg->is_register() ? arg->reg() : no_reg;
|
||||||
|
#endif
|
||||||
|
cgen()->frame()->Push(arg);
|
||||||
|
DoBranch(cc, hint);
|
||||||
|
*arg = cgen()->frame()->Pop();
|
||||||
|
ASSERT(arg->type() == arg_type);
|
||||||
|
ASSERT(!arg->is_register() || arg->reg().is(arg_reg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::Bind(Result* arg) {
|
||||||
|
if (cgen()->has_valid_frame()) {
|
||||||
|
cgen()->frame()->Push(arg);
|
||||||
|
}
|
||||||
|
DoBind();
|
||||||
|
*arg = cgen()->frame()->Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::Bind(Result* arg0, Result* arg1) {
|
||||||
|
if (cgen()->has_valid_frame()) {
|
||||||
|
cgen()->frame()->Push(arg0);
|
||||||
|
cgen()->frame()->Push(arg1);
|
||||||
|
}
|
||||||
|
DoBind();
|
||||||
|
*arg1 = cgen()->frame()->Pop();
|
||||||
|
*arg0 = cgen()->frame()->Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::ComputeEntryFrame() {
|
||||||
|
// Given: a collection of frames reaching by forward CFG edges and
|
||||||
|
// the directionality of the block. Compute: an entry frame for the
|
||||||
|
// block.
|
||||||
|
|
||||||
|
Counters::compute_entry_frame.Increment();
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (compiling_deferred_code_) {
|
||||||
|
ASSERT(reaching_frames_.length() > 1);
|
||||||
|
VirtualFrame* frame = reaching_frames_[0];
|
||||||
|
bool all_identical = true;
|
||||||
|
for (int i = 1; i < reaching_frames_.length(); i++) {
|
||||||
|
if (!frame->Equals(reaching_frames_[i])) {
|
||||||
|
all_identical = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(!all_identical || all_identical);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Choose an initial frame.
|
||||||
|
VirtualFrame* initial_frame = reaching_frames_[0];
|
||||||
|
|
||||||
|
// A list of pointers to frame elements in the entry frame. NULL
|
||||||
|
// indicates that the element has not yet been determined.
|
||||||
|
int length = initial_frame->element_count();
|
||||||
|
ZoneList<FrameElement*> elements(length);
|
||||||
|
|
||||||
|
// Initially populate the list of elements based on the initial
|
||||||
|
// frame.
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
FrameElement element = initial_frame->elements_[i];
|
||||||
|
// We do not allow copies or constants in bidirectional frames.
|
||||||
|
if (direction_ == BIDIRECTIONAL) {
|
||||||
|
if (element.is_constant() || element.is_copy()) {
|
||||||
|
elements.Add(NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elements.Add(&initial_frame->elements_[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute elements based on the other reaching frames.
|
||||||
|
if (reaching_frames_.length() > 1) {
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
FrameElement* element = elements[i];
|
||||||
|
for (int j = 1; j < reaching_frames_.length(); j++) {
|
||||||
|
// Element computation is monotonic: new information will not
|
||||||
|
// change our decision about undetermined or invalid elements.
|
||||||
|
if (element == NULL || !element->is_valid()) break;
|
||||||
|
|
||||||
|
FrameElement* other = &reaching_frames_[j]->elements_[i];
|
||||||
|
element = element->Combine(other);
|
||||||
|
if (element != NULL && !element->is_copy()) {
|
||||||
|
ASSERT(other != NULL);
|
||||||
|
// We overwrite the number information of one of the incoming frames.
|
||||||
|
// This is safe because we only use the frame for emitting merge code.
|
||||||
|
// The number information of incoming frames is not used anymore.
|
||||||
|
element->set_type_info(TypeInfo::Combine(element->type_info(),
|
||||||
|
other->type_info()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elements[i] = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the new frame. A freshly allocated frame has memory elements
|
||||||
|
// for the parameters and some platform-dependent elements (e.g.,
|
||||||
|
// return address). Replace those first.
|
||||||
|
entry_frame_ = new VirtualFrame();
|
||||||
|
int index = 0;
|
||||||
|
for (; index < entry_frame_->element_count(); index++) {
|
||||||
|
FrameElement* target = elements[index];
|
||||||
|
// If the element is determined, set it now. Count registers. Mark
|
||||||
|
// elements as copied exactly when they have a copy. Undetermined
|
||||||
|
// elements are initially recorded as if in memory.
|
||||||
|
if (target != NULL) {
|
||||||
|
entry_frame_->elements_[index] = *target;
|
||||||
|
InitializeEntryElement(index, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Then fill in the rest of the frame with new elements.
|
||||||
|
for (; index < length; index++) {
|
||||||
|
FrameElement* target = elements[index];
|
||||||
|
if (target == NULL) {
|
||||||
|
entry_frame_->elements_.Add(
|
||||||
|
FrameElement::MemoryElement(TypeInfo::Uninitialized()));
|
||||||
|
} else {
|
||||||
|
entry_frame_->elements_.Add(*target);
|
||||||
|
InitializeEntryElement(index, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate any still-undetermined frame elements to registers or
|
||||||
|
// memory, from the top down.
|
||||||
|
for (int i = length - 1; i >= 0; i--) {
|
||||||
|
if (elements[i] == NULL) {
|
||||||
|
// Loop over all the reaching frames to check whether the element
|
||||||
|
// is synced on all frames and to count the registers it occupies.
|
||||||
|
bool is_synced = true;
|
||||||
|
RegisterFile candidate_registers;
|
||||||
|
int best_count = kMinInt;
|
||||||
|
int best_reg_num = RegisterAllocator::kInvalidRegister;
|
||||||
|
TypeInfo info = TypeInfo::Uninitialized();
|
||||||
|
|
||||||
|
for (int j = 0; j < reaching_frames_.length(); j++) {
|
||||||
|
FrameElement element = reaching_frames_[j]->elements_[i];
|
||||||
|
if (direction_ == BIDIRECTIONAL) {
|
||||||
|
info = TypeInfo::Unknown();
|
||||||
|
} else if (!element.is_copy()) {
|
||||||
|
info = TypeInfo::Combine(info, element.type_info());
|
||||||
|
} else {
|
||||||
|
// New elements will not be copies, so get number information from
|
||||||
|
// backing element in the reaching frame.
|
||||||
|
info = TypeInfo::Combine(info,
|
||||||
|
reaching_frames_[j]->elements_[element.index()].type_info());
|
||||||
|
}
|
||||||
|
is_synced = is_synced && element.is_synced();
|
||||||
|
if (element.is_register() && !entry_frame_->is_used(element.reg())) {
|
||||||
|
// Count the register occurrence and remember it if better
|
||||||
|
// than the previous best.
|
||||||
|
int num = RegisterAllocator::ToNumber(element.reg());
|
||||||
|
candidate_registers.Use(num);
|
||||||
|
if (candidate_registers.count(num) > best_count) {
|
||||||
|
best_count = candidate_registers.count(num);
|
||||||
|
best_reg_num = num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must have a number type information now (not for copied elements).
|
||||||
|
ASSERT(entry_frame_->elements_[i].is_copy()
|
||||||
|
|| !info.IsUninitialized());
|
||||||
|
|
||||||
|
// If the value is synced on all frames, put it in memory. This
|
||||||
|
// costs nothing at the merge code but will incur a
|
||||||
|
// memory-to-register move when the value is needed later.
|
||||||
|
if (is_synced) {
|
||||||
|
// Already recorded as a memory element.
|
||||||
|
// Set combined number info.
|
||||||
|
entry_frame_->elements_[i].set_type_info(info);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to put it in a register. If there was no best choice
|
||||||
|
// consider any free register.
|
||||||
|
if (best_reg_num == RegisterAllocator::kInvalidRegister) {
|
||||||
|
for (int j = 0; j < RegisterAllocator::kNumRegisters; j++) {
|
||||||
|
if (!entry_frame_->is_used(j)) {
|
||||||
|
best_reg_num = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (best_reg_num != RegisterAllocator::kInvalidRegister) {
|
||||||
|
// If there was a register choice, use it. Preserve the copied
|
||||||
|
// flag on the element.
|
||||||
|
bool is_copied = entry_frame_->elements_[i].is_copied();
|
||||||
|
Register reg = RegisterAllocator::ToRegister(best_reg_num);
|
||||||
|
entry_frame_->elements_[i] =
|
||||||
|
FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED,
|
||||||
|
TypeInfo::Uninitialized());
|
||||||
|
if (is_copied) entry_frame_->elements_[i].set_copied();
|
||||||
|
entry_frame_->set_register_location(reg, i);
|
||||||
|
}
|
||||||
|
// Set combined number info.
|
||||||
|
entry_frame_->elements_[i].set_type_info(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have incoming backward edges assert we forget all number information.
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (direction_ == BIDIRECTIONAL) {
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
if (!entry_frame_->elements_[i].is_copy()) {
|
||||||
|
ASSERT(entry_frame_->elements_[i].type_info().IsUnknown());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// The stack pointer is at the highest synced element or the base of
|
||||||
|
// the expression stack.
|
||||||
|
int stack_pointer = length - 1;
|
||||||
|
while (stack_pointer >= entry_frame_->expression_base_index() &&
|
||||||
|
!entry_frame_->elements_[stack_pointer].is_synced()) {
|
||||||
|
stack_pointer--;
|
||||||
|
}
|
||||||
|
entry_frame_->stack_pointer_ = stack_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DeferredCode::DeferredCode()
|
||||||
|
: masm_(CodeGeneratorScope::Current()->masm()),
|
||||||
|
statement_position_(masm_->current_statement_position()),
|
||||||
|
position_(masm_->current_position()) {
|
||||||
|
ASSERT(statement_position_ != RelocInfo::kNoPosition);
|
||||||
|
ASSERT(position_ != RelocInfo::kNoPosition);
|
||||||
|
|
||||||
|
CodeGeneratorScope::Current()->AddDeferred(this);
|
||||||
|
#ifdef DEBUG
|
||||||
|
comment_ = "";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Copy the register locations from the code generator's frame.
|
||||||
|
// These are the registers that will be spilled on entry to the
|
||||||
|
// deferred code and restored on exit.
|
||||||
|
VirtualFrame* frame = CodeGeneratorScope::Current()->frame();
|
||||||
|
int sp_offset = frame->fp_relative(frame->stack_pointer_);
|
||||||
|
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
|
||||||
|
int loc = frame->register_location(i);
|
||||||
|
if (loc == VirtualFrame::kIllegalIndex) {
|
||||||
|
registers_[i] = kIgnore;
|
||||||
|
} else if (frame->elements_[loc].is_synced()) {
|
||||||
|
// Needs to be restored on exit but not saved on entry.
|
||||||
|
registers_[i] = frame->fp_relative(loc) | kSyncedFlag;
|
||||||
|
} else {
|
||||||
|
int offset = frame->fp_relative(loc);
|
||||||
|
registers_[i] = (offset < sp_offset) ? kPush : offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} } // namespace v8::internal
|
@ -30,6 +30,12 @@
|
|||||||
|
|
||||||
#include "virtual-frame-inl.h"
|
#include "virtual-frame-inl.h"
|
||||||
|
|
||||||
|
#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
|
||||||
|
#include "jump-target-heavy-inl.h"
|
||||||
|
#else
|
||||||
|
#include "jump-target-light-inl.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
@ -37,19 +43,6 @@ CodeGenerator* JumpTarget::cgen() {
|
|||||||
return CodeGeneratorScope::Current();
|
return CodeGeneratorScope::Current();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
|
|
||||||
FrameElement* element = &entry_frame_->elements_[index];
|
|
||||||
element->clear_copied();
|
|
||||||
if (target->is_register()) {
|
|
||||||
entry_frame_->set_register_location(target->reg(), index);
|
|
||||||
} else if (target->is_copy()) {
|
|
||||||
entry_frame_->elements_[target->index()].set_copied();
|
|
||||||
}
|
|
||||||
if (direction_ == BIDIRECTIONAL && !target->is_copy()) {
|
|
||||||
element->set_type_info(TypeInfo::Unknown());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
|
||||||
#endif // V8_JUMP_TARGET_INL_H_
|
#endif // V8_JUMP_TARGET_INL_H_
|
||||||
|
42
src/jump-target-light-inl.h
Normal file
42
src/jump-target-light-inl.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// 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_JUMP_TARGET_LIGHT_INL_H_
|
||||||
|
#define V8_JUMP_TARGET_LIGHT_INL_H_
|
||||||
|
|
||||||
|
#include "virtual-frame-inl.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} } // namespace v8::internal
|
||||||
|
|
||||||
|
#endif // V8_JUMP_TARGET_LIGHT_INL_H_
|
99
src/jump-target-light.cc
Normal file
99
src/jump-target-light.cc
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// 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 "codegen-inl.h"
|
||||||
|
#include "jump-target-inl.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::Jump(Result* arg) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::Bind(Result* arg) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::Bind(Result* arg0, Result* arg1) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JumpTarget::ComputeEntryFrame() {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DeferredCode::DeferredCode()
|
||||||
|
: masm_(CodeGeneratorScope::Current()->masm()),
|
||||||
|
statement_position_(masm_->current_statement_position()),
|
||||||
|
position_(masm_->current_position()) {
|
||||||
|
ASSERT(statement_position_ != RelocInfo::kNoPosition);
|
||||||
|
ASSERT(position_ != RelocInfo::kNoPosition);
|
||||||
|
|
||||||
|
CodeGeneratorScope::Current()->AddDeferred(this);
|
||||||
|
#ifdef DEBUG
|
||||||
|
comment_ = "";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Copy the register locations from the code generator's frame.
|
||||||
|
// These are the registers that will be spilled on entry to the
|
||||||
|
// deferred code and restored on exit.
|
||||||
|
VirtualFrame* frame = CodeGeneratorScope::Current()->frame();
|
||||||
|
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
|
||||||
|
int loc = frame->register_location(i);
|
||||||
|
if (loc == VirtualFrame::kIllegalIndex) {
|
||||||
|
registers_[i] = kIgnore;
|
||||||
|
} else {
|
||||||
|
// Needs to be restored on exit but not saved on entry.
|
||||||
|
registers_[i] = frame->fp_relative(loc) | kSyncedFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} } // namespace v8::internal
|
@ -48,319 +48,21 @@ void JumpTarget::Unuse() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void JumpTarget::ComputeEntryFrame() {
|
|
||||||
// Given: a collection of frames reaching by forward CFG edges and
|
|
||||||
// the directionality of the block. Compute: an entry frame for the
|
|
||||||
// block.
|
|
||||||
|
|
||||||
Counters::compute_entry_frame.Increment();
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (compiling_deferred_code_) {
|
|
||||||
ASSERT(reaching_frames_.length() > 1);
|
|
||||||
VirtualFrame* frame = reaching_frames_[0];
|
|
||||||
bool all_identical = true;
|
|
||||||
for (int i = 1; i < reaching_frames_.length(); i++) {
|
|
||||||
if (!frame->Equals(reaching_frames_[i])) {
|
|
||||||
all_identical = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ASSERT(!all_identical || all_identical);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Choose an initial frame.
|
|
||||||
VirtualFrame* initial_frame = reaching_frames_[0];
|
|
||||||
|
|
||||||
// A list of pointers to frame elements in the entry frame. NULL
|
|
||||||
// indicates that the element has not yet been determined.
|
|
||||||
int length = initial_frame->element_count();
|
|
||||||
ZoneList<FrameElement*> elements(length);
|
|
||||||
|
|
||||||
// Initially populate the list of elements based on the initial
|
|
||||||
// frame.
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
FrameElement element = initial_frame->elements_[i];
|
|
||||||
// We do not allow copies or constants in bidirectional frames.
|
|
||||||
if (direction_ == BIDIRECTIONAL) {
|
|
||||||
if (element.is_constant() || element.is_copy()) {
|
|
||||||
elements.Add(NULL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elements.Add(&initial_frame->elements_[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute elements based on the other reaching frames.
|
|
||||||
if (reaching_frames_.length() > 1) {
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
FrameElement* element = elements[i];
|
|
||||||
for (int j = 1; j < reaching_frames_.length(); j++) {
|
|
||||||
// Element computation is monotonic: new information will not
|
|
||||||
// change our decision about undetermined or invalid elements.
|
|
||||||
if (element == NULL || !element->is_valid()) break;
|
|
||||||
|
|
||||||
FrameElement* other = &reaching_frames_[j]->elements_[i];
|
|
||||||
element = element->Combine(other);
|
|
||||||
if (element != NULL && !element->is_copy()) {
|
|
||||||
ASSERT(other != NULL);
|
|
||||||
// We overwrite the number information of one of the incoming frames.
|
|
||||||
// This is safe because we only use the frame for emitting merge code.
|
|
||||||
// The number information of incoming frames is not used anymore.
|
|
||||||
element->set_type_info(TypeInfo::Combine(element->type_info(),
|
|
||||||
other->type_info()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elements[i] = element;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the new frame. A freshly allocated frame has memory elements
|
|
||||||
// for the parameters and some platform-dependent elements (e.g.,
|
|
||||||
// return address). Replace those first.
|
|
||||||
entry_frame_ = new VirtualFrame();
|
|
||||||
int index = 0;
|
|
||||||
for (; index < entry_frame_->element_count(); index++) {
|
|
||||||
FrameElement* target = elements[index];
|
|
||||||
// If the element is determined, set it now. Count registers. Mark
|
|
||||||
// elements as copied exactly when they have a copy. Undetermined
|
|
||||||
// elements are initially recorded as if in memory.
|
|
||||||
if (target != NULL) {
|
|
||||||
entry_frame_->elements_[index] = *target;
|
|
||||||
InitializeEntryElement(index, target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Then fill in the rest of the frame with new elements.
|
|
||||||
for (; index < length; index++) {
|
|
||||||
FrameElement* target = elements[index];
|
|
||||||
if (target == NULL) {
|
|
||||||
entry_frame_->elements_.Add(
|
|
||||||
FrameElement::MemoryElement(TypeInfo::Uninitialized()));
|
|
||||||
} else {
|
|
||||||
entry_frame_->elements_.Add(*target);
|
|
||||||
InitializeEntryElement(index, target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate any still-undetermined frame elements to registers or
|
|
||||||
// memory, from the top down.
|
|
||||||
for (int i = length - 1; i >= 0; i--) {
|
|
||||||
if (elements[i] == NULL) {
|
|
||||||
// Loop over all the reaching frames to check whether the element
|
|
||||||
// is synced on all frames and to count the registers it occupies.
|
|
||||||
bool is_synced = true;
|
|
||||||
RegisterFile candidate_registers;
|
|
||||||
int best_count = kMinInt;
|
|
||||||
int best_reg_num = RegisterAllocator::kInvalidRegister;
|
|
||||||
TypeInfo info = TypeInfo::Uninitialized();
|
|
||||||
|
|
||||||
for (int j = 0; j < reaching_frames_.length(); j++) {
|
|
||||||
FrameElement element = reaching_frames_[j]->elements_[i];
|
|
||||||
if (direction_ == BIDIRECTIONAL) {
|
|
||||||
info = TypeInfo::Unknown();
|
|
||||||
} else if (!element.is_copy()) {
|
|
||||||
info = TypeInfo::Combine(info, element.type_info());
|
|
||||||
} else {
|
|
||||||
// New elements will not be copies, so get number information from
|
|
||||||
// backing element in the reaching frame.
|
|
||||||
info = TypeInfo::Combine(info,
|
|
||||||
reaching_frames_[j]->elements_[element.index()].type_info());
|
|
||||||
}
|
|
||||||
is_synced = is_synced && element.is_synced();
|
|
||||||
if (element.is_register() && !entry_frame_->is_used(element.reg())) {
|
|
||||||
// Count the register occurrence and remember it if better
|
|
||||||
// than the previous best.
|
|
||||||
int num = RegisterAllocator::ToNumber(element.reg());
|
|
||||||
candidate_registers.Use(num);
|
|
||||||
if (candidate_registers.count(num) > best_count) {
|
|
||||||
best_count = candidate_registers.count(num);
|
|
||||||
best_reg_num = num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We must have a number type information now (not for copied elements).
|
|
||||||
ASSERT(entry_frame_->elements_[i].is_copy()
|
|
||||||
|| !info.IsUninitialized());
|
|
||||||
|
|
||||||
// If the value is synced on all frames, put it in memory. This
|
|
||||||
// costs nothing at the merge code but will incur a
|
|
||||||
// memory-to-register move when the value is needed later.
|
|
||||||
if (is_synced) {
|
|
||||||
// Already recorded as a memory element.
|
|
||||||
// Set combined number info.
|
|
||||||
entry_frame_->elements_[i].set_type_info(info);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to put it in a register. If there was no best choice
|
|
||||||
// consider any free register.
|
|
||||||
if (best_reg_num == RegisterAllocator::kInvalidRegister) {
|
|
||||||
for (int j = 0; j < RegisterAllocator::kNumRegisters; j++) {
|
|
||||||
if (!entry_frame_->is_used(j)) {
|
|
||||||
best_reg_num = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (best_reg_num != RegisterAllocator::kInvalidRegister) {
|
|
||||||
// If there was a register choice, use it. Preserve the copied
|
|
||||||
// flag on the element.
|
|
||||||
bool is_copied = entry_frame_->elements_[i].is_copied();
|
|
||||||
Register reg = RegisterAllocator::ToRegister(best_reg_num);
|
|
||||||
entry_frame_->elements_[i] =
|
|
||||||
FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED,
|
|
||||||
TypeInfo::Uninitialized());
|
|
||||||
if (is_copied) entry_frame_->elements_[i].set_copied();
|
|
||||||
entry_frame_->set_register_location(reg, i);
|
|
||||||
}
|
|
||||||
// Set combined number info.
|
|
||||||
entry_frame_->elements_[i].set_type_info(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have incoming backward edges assert we forget all number information.
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (direction_ == BIDIRECTIONAL) {
|
|
||||||
for (int i = 0; i < length; ++i) {
|
|
||||||
if (!entry_frame_->elements_[i].is_copy()) {
|
|
||||||
ASSERT(entry_frame_->elements_[i].type_info().IsUnknown());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The stack pointer is at the highest synced element or the base of
|
|
||||||
// the expression stack.
|
|
||||||
int stack_pointer = length - 1;
|
|
||||||
while (stack_pointer >= entry_frame_->expression_base_index() &&
|
|
||||||
!entry_frame_->elements_[stack_pointer].is_synced()) {
|
|
||||||
stack_pointer--;
|
|
||||||
}
|
|
||||||
entry_frame_->stack_pointer_ = stack_pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void JumpTarget::Jump() {
|
void JumpTarget::Jump() {
|
||||||
DoJump();
|
DoJump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void JumpTarget::Jump(Result* arg) {
|
|
||||||
ASSERT(cgen()->has_valid_frame());
|
|
||||||
|
|
||||||
cgen()->frame()->Push(arg);
|
|
||||||
DoJump();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void JumpTarget::Branch(Condition cc, Hint hint) {
|
void JumpTarget::Branch(Condition cc, Hint hint) {
|
||||||
DoBranch(cc, hint);
|
DoBranch(cc, hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define DECLARE_ARGCHECK_VARS(name) \
|
|
||||||
Result::Type name##_type = name->type(); \
|
|
||||||
Register name##_reg = name->is_register() ? name->reg() : no_reg
|
|
||||||
|
|
||||||
#define ASSERT_ARGCHECK(name) \
|
|
||||||
ASSERT(name->type() == name##_type); \
|
|
||||||
ASSERT(!name->is_register() || name->reg().is(name##_reg))
|
|
||||||
|
|
||||||
#else
|
|
||||||
#define DECLARE_ARGCHECK_VARS(name) do {} while (false)
|
|
||||||
|
|
||||||
#define ASSERT_ARGCHECK(name) do {} while (false)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
|
|
||||||
ASSERT(cgen()->has_valid_frame());
|
|
||||||
|
|
||||||
// We want to check that non-frame registers at the call site stay in
|
|
||||||
// the same registers on the fall-through branch.
|
|
||||||
DECLARE_ARGCHECK_VARS(arg);
|
|
||||||
|
|
||||||
cgen()->frame()->Push(arg);
|
|
||||||
DoBranch(cc, hint);
|
|
||||||
*arg = cgen()->frame()->Pop();
|
|
||||||
|
|
||||||
ASSERT_ARGCHECK(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
|
|
||||||
ASSERT(cgen()->has_valid_frame());
|
|
||||||
|
|
||||||
// We want to check that non-frame registers at the call site stay in
|
|
||||||
// the same registers on the fall-through branch.
|
|
||||||
DECLARE_ARGCHECK_VARS(arg0);
|
|
||||||
DECLARE_ARGCHECK_VARS(arg1);
|
|
||||||
|
|
||||||
cgen()->frame()->Push(arg0);
|
|
||||||
cgen()->frame()->Push(arg1);
|
|
||||||
DoBranch(cc, hint);
|
|
||||||
*arg1 = cgen()->frame()->Pop();
|
|
||||||
*arg0 = cgen()->frame()->Pop();
|
|
||||||
|
|
||||||
ASSERT_ARGCHECK(arg0);
|
|
||||||
ASSERT_ARGCHECK(arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
|
|
||||||
ASSERT(cgen()->has_valid_frame());
|
|
||||||
|
|
||||||
int count = cgen()->frame()->height() - expected_height_;
|
|
||||||
if (count > 0) {
|
|
||||||
// We negate and branch here rather than using DoBranch's negate
|
|
||||||
// and branch. This gives us a hook to remove statement state
|
|
||||||
// from the frame.
|
|
||||||
JumpTarget fall_through;
|
|
||||||
// Branch to fall through will not negate, because it is a
|
|
||||||
// forward-only target.
|
|
||||||
fall_through.Branch(NegateCondition(cc), NegateHint(hint));
|
|
||||||
Jump(arg); // May emit merge code here.
|
|
||||||
fall_through.Bind();
|
|
||||||
} else {
|
|
||||||
DECLARE_ARGCHECK_VARS(arg);
|
|
||||||
cgen()->frame()->Push(arg);
|
|
||||||
DoBranch(cc, hint);
|
|
||||||
*arg = cgen()->frame()->Pop();
|
|
||||||
ASSERT_ARGCHECK(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef DECLARE_ARGCHECK_VARS
|
|
||||||
#undef ASSERT_ARGCHECK
|
|
||||||
|
|
||||||
|
|
||||||
void JumpTarget::Bind() {
|
void JumpTarget::Bind() {
|
||||||
DoBind();
|
DoBind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void JumpTarget::Bind(Result* arg) {
|
|
||||||
if (cgen()->has_valid_frame()) {
|
|
||||||
cgen()->frame()->Push(arg);
|
|
||||||
}
|
|
||||||
DoBind();
|
|
||||||
*arg = cgen()->frame()->Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void JumpTarget::Bind(Result* arg0, Result* arg1) {
|
|
||||||
if (cgen()->has_valid_frame()) {
|
|
||||||
cgen()->frame()->Push(arg0);
|
|
||||||
cgen()->frame()->Push(arg1);
|
|
||||||
}
|
|
||||||
DoBind();
|
|
||||||
*arg1 = cgen()->frame()->Pop();
|
|
||||||
*arg0 = cgen()->frame()->Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
|
void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
|
||||||
ASSERT(reaching_frames_.length() == merge_labels_.length());
|
ASSERT(reaching_frames_.length() == merge_labels_.length());
|
||||||
ASSERT(entry_frame_ == NULL);
|
ASSERT(entry_frame_ == NULL);
|
||||||
|
136
src/virtual-frame-heavy-inl.h
Normal file
136
src/virtual-frame-heavy-inl.h
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
// 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_HEAVY_INL_H_
|
||||||
|
#define V8_VIRTUAL_FRAME_HEAVY_INL_H_
|
||||||
|
|
||||||
|
#include "type-info.h"
|
||||||
|
#include "register-allocator.h"
|
||||||
|
#include "scopes.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// On entry to a function, the virtual frame already contains the receiver,
|
||||||
|
// the parameters, and a return address. All frame elements are in memory.
|
||||||
|
VirtualFrame::VirtualFrame()
|
||||||
|
: elements_(parameter_count() + local_count() + kPreallocatedElements),
|
||||||
|
stack_pointer_(parameter_count() + 1) { // 0-based index of TOS.
|
||||||
|
for (int i = 0; i <= stack_pointer_; i++) {
|
||||||
|
elements_.Add(FrameElement::MemoryElement(TypeInfo::Unknown()));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
|
||||||
|
register_locations_[i] = kIllegalIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// When cloned, a frame is a deep copy of the original.
|
||||||
|
VirtualFrame::VirtualFrame(VirtualFrame* original)
|
||||||
|
: elements_(original->element_count()),
|
||||||
|
stack_pointer_(original->stack_pointer_) {
|
||||||
|
elements_.AddAll(original->elements_);
|
||||||
|
// Copy register locations from original.
|
||||||
|
memcpy(®ister_locations_,
|
||||||
|
original->register_locations_,
|
||||||
|
sizeof(register_locations_));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::PushFrameSlotAt(int index) {
|
||||||
|
elements_.Add(CopyElementAt(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::Push(Register reg, TypeInfo info) {
|
||||||
|
if (is_used(reg)) {
|
||||||
|
int index = register_location(reg);
|
||||||
|
FrameElement element = CopyElementAt(index, info);
|
||||||
|
elements_.Add(element);
|
||||||
|
} else {
|
||||||
|
Use(reg, element_count());
|
||||||
|
FrameElement element =
|
||||||
|
FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED, info);
|
||||||
|
elements_.Add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::Push(Handle<Object> value) {
|
||||||
|
FrameElement element =
|
||||||
|
FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
|
||||||
|
elements_.Add(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool VirtualFrame::Equals(VirtualFrame* other) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
|
||||||
|
if (register_location(i) != other->register_location(i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (element_count() != other->element_count()) return false;
|
||||||
|
#endif
|
||||||
|
if (stack_pointer_ != other->stack_pointer_) return false;
|
||||||
|
for (int i = 0; i < element_count(); i++) {
|
||||||
|
if (!elements_[i].Equals(other->elements_[i])) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::SetTypeForLocalAt(int index, TypeInfo info) {
|
||||||
|
elements_[local0_index() + index].set_type_info(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Make the type of all elements be MEMORY.
|
||||||
|
void VirtualFrame::SpillAll() {
|
||||||
|
for (int i = 0; i < element_count(); i++) {
|
||||||
|
SpillElementAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::PrepareForReturn() {
|
||||||
|
// Spill all locals. This is necessary to make sure all locals have
|
||||||
|
// the right value when breaking at the return site in the debugger.
|
||||||
|
for (int i = 0; i < expression_base_index(); i++) {
|
||||||
|
SpillElementAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::SetTypeForParamAt(int index, TypeInfo info) {
|
||||||
|
elements_[param0_index() + index].set_type_info(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
} } // namespace v8::internal
|
||||||
|
|
||||||
|
#endif // V8_VIRTUAL_FRAME_HEAVY_INL_H_
|
298
src/virtual-frame-heavy.cc
Normal file
298
src/virtual-frame-heavy.cc
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
// 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 "codegen-inl.h"
|
||||||
|
#include "register-allocator-inl.h"
|
||||||
|
#include "virtual-frame-inl.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
void VirtualFrame::SetElementAt(int index, Result* value) {
|
||||||
|
int frame_index = element_count() - index - 1;
|
||||||
|
ASSERT(frame_index >= 0);
|
||||||
|
ASSERT(frame_index < element_count());
|
||||||
|
ASSERT(value->is_valid());
|
||||||
|
FrameElement original = elements_[frame_index];
|
||||||
|
|
||||||
|
// Early exit if the element is the same as the one being set.
|
||||||
|
bool same_register = original.is_register()
|
||||||
|
&& value->is_register()
|
||||||
|
&& original.reg().is(value->reg());
|
||||||
|
bool same_constant = original.is_constant()
|
||||||
|
&& value->is_constant()
|
||||||
|
&& original.handle().is_identical_to(value->handle());
|
||||||
|
if (same_register || same_constant) {
|
||||||
|
value->Unuse();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InvalidateFrameSlotAt(frame_index);
|
||||||
|
|
||||||
|
if (value->is_register()) {
|
||||||
|
if (is_used(value->reg())) {
|
||||||
|
// The register already appears on the frame. Either the existing
|
||||||
|
// register element, or the new element at frame_index, must be made
|
||||||
|
// a copy.
|
||||||
|
int i = register_location(value->reg());
|
||||||
|
|
||||||
|
if (i < frame_index) {
|
||||||
|
// The register FrameElement is lower in the frame than the new copy.
|
||||||
|
elements_[frame_index] = CopyElementAt(i);
|
||||||
|
} else {
|
||||||
|
// There was an early bailout for the case of setting a
|
||||||
|
// register element to itself.
|
||||||
|
ASSERT(i != frame_index);
|
||||||
|
elements_[frame_index] = elements_[i];
|
||||||
|
elements_[i] = CopyElementAt(frame_index);
|
||||||
|
if (elements_[frame_index].is_synced()) {
|
||||||
|
elements_[i].set_sync();
|
||||||
|
}
|
||||||
|
elements_[frame_index].clear_sync();
|
||||||
|
set_register_location(value->reg(), frame_index);
|
||||||
|
for (int j = i + 1; j < element_count(); j++) {
|
||||||
|
if (elements_[j].is_copy() && elements_[j].index() == i) {
|
||||||
|
elements_[j].set_index(frame_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The register value->reg() was not already used on the frame.
|
||||||
|
Use(value->reg(), frame_index);
|
||||||
|
elements_[frame_index] =
|
||||||
|
FrameElement::RegisterElement(value->reg(),
|
||||||
|
FrameElement::NOT_SYNCED,
|
||||||
|
value->type_info());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ASSERT(value->is_constant());
|
||||||
|
elements_[frame_index] =
|
||||||
|
FrameElement::ConstantElement(value->handle(),
|
||||||
|
FrameElement::NOT_SYNCED);
|
||||||
|
}
|
||||||
|
value->Unuse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create a duplicate of an existing valid frame element.
|
||||||
|
// We can pass an optional number type information that will override the
|
||||||
|
// existing information about the backing element. The new information must
|
||||||
|
// not conflict with the existing type information and must be equally or
|
||||||
|
// more precise. The default parameter value kUninitialized means that there
|
||||||
|
// is no additional information.
|
||||||
|
FrameElement VirtualFrame::CopyElementAt(int index, TypeInfo info) {
|
||||||
|
ASSERT(index >= 0);
|
||||||
|
ASSERT(index < element_count());
|
||||||
|
|
||||||
|
FrameElement target = elements_[index];
|
||||||
|
FrameElement result;
|
||||||
|
|
||||||
|
switch (target.type()) {
|
||||||
|
case FrameElement::CONSTANT:
|
||||||
|
// We do not copy constants and instead return a fresh unsynced
|
||||||
|
// constant.
|
||||||
|
result = FrameElement::ConstantElement(target.handle(),
|
||||||
|
FrameElement::NOT_SYNCED);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FrameElement::COPY:
|
||||||
|
// We do not allow copies of copies, so we follow one link to
|
||||||
|
// the actual backing store of a copy before making a copy.
|
||||||
|
index = target.index();
|
||||||
|
ASSERT(elements_[index].is_memory() || elements_[index].is_register());
|
||||||
|
// Fall through.
|
||||||
|
|
||||||
|
case FrameElement::MEMORY: // Fall through.
|
||||||
|
case FrameElement::REGISTER: {
|
||||||
|
// All copies are backed by memory or register locations.
|
||||||
|
result.set_type(FrameElement::COPY);
|
||||||
|
result.clear_copied();
|
||||||
|
result.clear_sync();
|
||||||
|
result.set_index(index);
|
||||||
|
elements_[index].set_copied();
|
||||||
|
// Update backing element's number information.
|
||||||
|
TypeInfo existing = elements_[index].type_info();
|
||||||
|
ASSERT(!existing.IsUninitialized());
|
||||||
|
// Assert that the new type information (a) does not conflict with the
|
||||||
|
// existing one and (b) is equally or more precise.
|
||||||
|
ASSERT((info.ToInt() & existing.ToInt()) == existing.ToInt());
|
||||||
|
ASSERT((info.ToInt() | existing.ToInt()) == info.ToInt());
|
||||||
|
|
||||||
|
elements_[index].set_type_info(!info.IsUninitialized()
|
||||||
|
? info
|
||||||
|
: existing);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FrameElement::INVALID:
|
||||||
|
// We should not try to copy invalid elements.
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Modify the state of the virtual frame to match the actual frame by adding
|
||||||
|
// extra in-memory elements to the top of the virtual frame. The extra
|
||||||
|
// elements will be externally materialized on the actual frame (eg, by
|
||||||
|
// pushing an exception handler). No code is emitted.
|
||||||
|
void VirtualFrame::Adjust(int count) {
|
||||||
|
ASSERT(count >= 0);
|
||||||
|
ASSERT(stack_pointer_ == element_count() - 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
elements_.Add(FrameElement::MemoryElement(TypeInfo::Unknown()));
|
||||||
|
}
|
||||||
|
stack_pointer_ += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::ForgetElements(int count) {
|
||||||
|
ASSERT(count >= 0);
|
||||||
|
ASSERT(element_count() >= count);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
FrameElement last = elements_.RemoveLast();
|
||||||
|
if (last.is_register()) {
|
||||||
|
// A hack to properly count register references for the code
|
||||||
|
// generator's current frame and also for other frames. The
|
||||||
|
// same code appears in PrepareMergeTo.
|
||||||
|
if (cgen()->frame() == this) {
|
||||||
|
Unuse(last.reg());
|
||||||
|
} else {
|
||||||
|
set_register_location(last.reg(), kIllegalIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Make the type of the element at a given index be MEMORY.
|
||||||
|
void VirtualFrame::SpillElementAt(int index) {
|
||||||
|
if (!elements_[index].is_valid()) return;
|
||||||
|
|
||||||
|
SyncElementAt(index);
|
||||||
|
// Number type information is preserved.
|
||||||
|
// Copies get their number information from their backing element.
|
||||||
|
TypeInfo info;
|
||||||
|
if (!elements_[index].is_copy()) {
|
||||||
|
info = elements_[index].type_info();
|
||||||
|
} else {
|
||||||
|
info = elements_[elements_[index].index()].type_info();
|
||||||
|
}
|
||||||
|
// The element is now in memory. Its copied flag is preserved.
|
||||||
|
FrameElement new_element = FrameElement::MemoryElement(info);
|
||||||
|
if (elements_[index].is_copied()) {
|
||||||
|
new_element.set_copied();
|
||||||
|
}
|
||||||
|
if (elements_[index].is_untagged_int32()) {
|
||||||
|
new_element.set_untagged_int32(true);
|
||||||
|
}
|
||||||
|
if (elements_[index].is_register()) {
|
||||||
|
Unuse(elements_[index].reg());
|
||||||
|
}
|
||||||
|
elements_[index] = new_element;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clear the dirty bit for the element at a given index.
|
||||||
|
void VirtualFrame::SyncElementAt(int index) {
|
||||||
|
if (index <= stack_pointer_) {
|
||||||
|
if (!elements_[index].is_synced()) SyncElementBelowStackPointer(index);
|
||||||
|
} else if (index == stack_pointer_ + 1) {
|
||||||
|
SyncElementByPushing(index);
|
||||||
|
} else {
|
||||||
|
SyncRange(stack_pointer_ + 1, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) {
|
||||||
|
// Perform state changes on this frame that will make merge to the
|
||||||
|
// expected frame simpler or else increase the likelihood that his
|
||||||
|
// frame will match another.
|
||||||
|
for (int i = 0; i < element_count(); i++) {
|
||||||
|
FrameElement source = elements_[i];
|
||||||
|
FrameElement target = expected->elements_[i];
|
||||||
|
|
||||||
|
if (!target.is_valid() ||
|
||||||
|
(target.is_memory() && !source.is_memory() && source.is_synced())) {
|
||||||
|
// No code needs to be generated to invalidate valid elements.
|
||||||
|
// No code needs to be generated to move values to memory if
|
||||||
|
// they are already synced. We perform those moves here, before
|
||||||
|
// merging.
|
||||||
|
if (source.is_register()) {
|
||||||
|
// If the frame is the code generator's current frame, we have
|
||||||
|
// to decrement both the frame-internal and global register
|
||||||
|
// counts.
|
||||||
|
if (cgen()->frame() == this) {
|
||||||
|
Unuse(source.reg());
|
||||||
|
} else {
|
||||||
|
set_register_location(source.reg(), kIllegalIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elements_[i] = target;
|
||||||
|
} else if (target.is_register() && !target.is_synced() &&
|
||||||
|
!source.is_memory()) {
|
||||||
|
// If an element's target is a register that doesn't need to be
|
||||||
|
// synced, and the element is not in memory, then the sync state
|
||||||
|
// of the element is irrelevant. We clear the sync bit.
|
||||||
|
ASSERT(source.is_valid());
|
||||||
|
elements_[i].clear_sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
|
||||||
|
ASSERT(height() >= dropped_args);
|
||||||
|
ASSERT(height() >= spilled_args);
|
||||||
|
ASSERT(dropped_args <= spilled_args);
|
||||||
|
|
||||||
|
SyncRange(0, element_count() - 1);
|
||||||
|
// Spill registers.
|
||||||
|
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
|
||||||
|
if (is_used(i)) {
|
||||||
|
SpillElementAt(register_location(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spill the arguments.
|
||||||
|
for (int i = element_count() - spilled_args; i < element_count(); i++) {
|
||||||
|
if (!elements_[i].is_memory()) {
|
||||||
|
SpillElementAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forget the frame elements that will be popped by the call.
|
||||||
|
Forget(dropped_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} } // namespace v8::internal
|
@ -30,62 +30,16 @@
|
|||||||
|
|
||||||
#include "virtual-frame.h"
|
#include "virtual-frame.h"
|
||||||
|
|
||||||
|
#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
|
||||||
|
#include "virtual-frame-heavy-inl.h"
|
||||||
|
#else
|
||||||
|
#include "virtual-frame-light-inl.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
|
||||||
// On entry to a function, the virtual frame already contains the receiver,
|
|
||||||
// the parameters, and a return address. All frame elements are in memory.
|
|
||||||
VirtualFrame::VirtualFrame()
|
|
||||||
: elements_(parameter_count() + local_count() + kPreallocatedElements),
|
|
||||||
stack_pointer_(parameter_count() + 1) { // 0-based index of TOS.
|
|
||||||
for (int i = 0; i <= stack_pointer_; i++) {
|
|
||||||
elements_.Add(FrameElement::MemoryElement(TypeInfo::Unknown()));
|
|
||||||
}
|
|
||||||
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
|
|
||||||
register_locations_[i] = kIllegalIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// When cloned, a frame is a deep copy of the original.
|
|
||||||
VirtualFrame::VirtualFrame(VirtualFrame* original)
|
|
||||||
: elements_(original->element_count()),
|
|
||||||
stack_pointer_(original->stack_pointer_) {
|
|
||||||
elements_.AddAll(original->elements_);
|
|
||||||
// Copy register locations from original.
|
|
||||||
memcpy(®ister_locations_,
|
|
||||||
original->register_locations_,
|
|
||||||
sizeof(register_locations_));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::PushFrameSlotAt(int index) {
|
|
||||||
elements_.Add(CopyElementAt(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::Push(Register reg, TypeInfo info) {
|
|
||||||
if (is_used(reg)) {
|
|
||||||
int index = register_location(reg);
|
|
||||||
FrameElement element = CopyElementAt(index, info);
|
|
||||||
elements_.Add(element);
|
|
||||||
} else {
|
|
||||||
Use(reg, element_count());
|
|
||||||
FrameElement element =
|
|
||||||
FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED, info);
|
|
||||||
elements_.Add(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::Push(Handle<Object> value) {
|
|
||||||
FrameElement element =
|
|
||||||
FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
|
|
||||||
elements_.Add(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::Push(Smi* value) {
|
void VirtualFrame::Push(Smi* value) {
|
||||||
Push(Handle<Object> (value));
|
Push(Handle<Object> (value));
|
||||||
}
|
}
|
||||||
@ -101,35 +55,6 @@ void VirtualFrame::Nip(int num_dropped) {
|
|||||||
SetElementAt(0, &tos);
|
SetElementAt(0, &tos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool VirtualFrame::Equals(VirtualFrame* other) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
|
|
||||||
if (register_location(i) != other->register_location(i)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (element_count() != other->element_count()) return false;
|
|
||||||
#endif
|
|
||||||
if (stack_pointer_ != other->stack_pointer_) return false;
|
|
||||||
for (int i = 0; i < element_count(); i++) {
|
|
||||||
if (!elements_[i].Equals(other->elements_[i])) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::SetTypeForLocalAt(int index, TypeInfo info) {
|
|
||||||
elements_[local0_index() + index].set_type_info(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::SetTypeForParamAt(int index, TypeInfo info) {
|
|
||||||
elements_[param0_index() + index].set_type_info(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
|
||||||
#endif // V8_VIRTUAL_FRAME_INL_H_
|
#endif // V8_VIRTUAL_FRAME_INL_H_
|
||||||
|
95
src/virtual-frame-light-inl.h
Normal file
95
src/virtual-frame-light-inl.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
// 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_LIGHT_INL_H_
|
||||||
|
#define V8_VIRTUAL_FRAME_LIGHT_INL_H_
|
||||||
|
|
||||||
|
#include "type-info.h"
|
||||||
|
#include "register-allocator.h"
|
||||||
|
#include "scopes.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// On entry to a function, the virtual frame already contains the receiver,
|
||||||
|
// the parameters, and a return address. All frame elements are in memory.
|
||||||
|
VirtualFrame::VirtualFrame()
|
||||||
|
: element_count_(parameter_count() + 2),
|
||||||
|
stack_pointer_(parameter_count() + 1) {
|
||||||
|
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
|
||||||
|
register_locations_[i] = kIllegalIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// When cloned, a frame is a deep copy of the original.
|
||||||
|
VirtualFrame::VirtualFrame(VirtualFrame* original)
|
||||||
|
: element_count_(original->element_count()),
|
||||||
|
stack_pointer_(original->stack_pointer_) {
|
||||||
|
memcpy(®ister_locations_,
|
||||||
|
original->register_locations_,
|
||||||
|
sizeof(register_locations_));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::Push(Handle<Object> value) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool VirtualFrame::Equals(VirtualFrame* other) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
|
||||||
|
if (register_location(i) != other->register_location(i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (element_count() != other->element_count()) return false;
|
||||||
|
#endif
|
||||||
|
if (stack_pointer_ != other->stack_pointer_) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::SetTypeForLocalAt(int index, TypeInfo info) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Everything is always spilled anyway.
|
||||||
|
void VirtualFrame::SpillAll() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VirtualFrame::PrepareForReturn() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} } // namespace v8::internal
|
||||||
|
|
||||||
|
#endif // V8_VIRTUAL_FRAME_LIGHT_INL_H_
|
52
src/virtual-frame-light.cc
Normal file
52
src/virtual-frame-light.cc
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// 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 "codegen-inl.h"
|
||||||
|
#include "register-allocator-inl.h"
|
||||||
|
#include "virtual-frame-inl.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
void VirtualFrame::Adjust(int count) {
|
||||||
|
ASSERT(count >= 0);
|
||||||
|
ASSERT(stack_pointer_ == element_count() - 1);
|
||||||
|
|
||||||
|
element_count_ += count;
|
||||||
|
stack_pointer_ += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Make the type of the element at a given index be MEMORY.
|
||||||
|
void VirtualFrame::SpillElementAt(int index) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} } // namespace v8::internal
|
@ -37,99 +37,6 @@ namespace internal {
|
|||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// VirtualFrame implementation.
|
// VirtualFrame implementation.
|
||||||
|
|
||||||
// Create a duplicate of an existing valid frame element.
|
|
||||||
// We can pass an optional number type information that will override the
|
|
||||||
// existing information about the backing element. The new information must
|
|
||||||
// not conflict with the existing type information and must be equally or
|
|
||||||
// more precise. The default parameter value kUninitialized means that there
|
|
||||||
// is no additional information.
|
|
||||||
FrameElement VirtualFrame::CopyElementAt(int index, TypeInfo info) {
|
|
||||||
ASSERT(index >= 0);
|
|
||||||
ASSERT(index < element_count());
|
|
||||||
|
|
||||||
FrameElement target = elements_[index];
|
|
||||||
FrameElement result;
|
|
||||||
|
|
||||||
switch (target.type()) {
|
|
||||||
case FrameElement::CONSTANT:
|
|
||||||
// We do not copy constants and instead return a fresh unsynced
|
|
||||||
// constant.
|
|
||||||
result = FrameElement::ConstantElement(target.handle(),
|
|
||||||
FrameElement::NOT_SYNCED);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FrameElement::COPY:
|
|
||||||
// We do not allow copies of copies, so we follow one link to
|
|
||||||
// the actual backing store of a copy before making a copy.
|
|
||||||
index = target.index();
|
|
||||||
ASSERT(elements_[index].is_memory() || elements_[index].is_register());
|
|
||||||
// Fall through.
|
|
||||||
|
|
||||||
case FrameElement::MEMORY: // Fall through.
|
|
||||||
case FrameElement::REGISTER: {
|
|
||||||
// All copies are backed by memory or register locations.
|
|
||||||
result.set_type(FrameElement::COPY);
|
|
||||||
result.clear_copied();
|
|
||||||
result.clear_sync();
|
|
||||||
result.set_index(index);
|
|
||||||
elements_[index].set_copied();
|
|
||||||
// Update backing element's number information.
|
|
||||||
TypeInfo existing = elements_[index].type_info();
|
|
||||||
ASSERT(!existing.IsUninitialized());
|
|
||||||
// Assert that the new type information (a) does not conflict with the
|
|
||||||
// existing one and (b) is equally or more precise.
|
|
||||||
ASSERT((info.ToInt() & existing.ToInt()) == existing.ToInt());
|
|
||||||
ASSERT((info.ToInt() | existing.ToInt()) == info.ToInt());
|
|
||||||
|
|
||||||
elements_[index].set_type_info(!info.IsUninitialized()
|
|
||||||
? info
|
|
||||||
: existing);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FrameElement::INVALID:
|
|
||||||
// We should not try to copy invalid elements.
|
|
||||||
UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Modify the state of the virtual frame to match the actual frame by adding
|
|
||||||
// extra in-memory elements to the top of the virtual frame. The extra
|
|
||||||
// elements will be externally materialized on the actual frame (eg, by
|
|
||||||
// pushing an exception handler). No code is emitted.
|
|
||||||
void VirtualFrame::Adjust(int count) {
|
|
||||||
ASSERT(count >= 0);
|
|
||||||
ASSERT(stack_pointer_ == element_count() - 1);
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
elements_.Add(FrameElement::MemoryElement(TypeInfo::Unknown()));
|
|
||||||
}
|
|
||||||
stack_pointer_ += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::ForgetElements(int count) {
|
|
||||||
ASSERT(count >= 0);
|
|
||||||
ASSERT(element_count() >= count);
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
FrameElement last = elements_.RemoveLast();
|
|
||||||
if (last.is_register()) {
|
|
||||||
// A hack to properly count register references for the code
|
|
||||||
// generator's current frame and also for other frames. The
|
|
||||||
// same code appears in PrepareMergeTo.
|
|
||||||
if (cgen()->frame() == this) {
|
|
||||||
Unuse(last.reg());
|
|
||||||
} else {
|
|
||||||
set_register_location(last.reg(), kIllegalIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// If there are any registers referenced only by the frame, spill one.
|
// If there are any registers referenced only by the frame, spill one.
|
||||||
Register VirtualFrame::SpillAnyRegister() {
|
Register VirtualFrame::SpillAnyRegister() {
|
||||||
// Find the leftmost (ordered by register number) register whose only
|
// Find the leftmost (ordered by register number) register whose only
|
||||||
@ -145,191 +52,6 @@ Register VirtualFrame::SpillAnyRegister() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Make the type of the element at a given index be MEMORY.
|
|
||||||
void VirtualFrame::SpillElementAt(int index) {
|
|
||||||
if (!elements_[index].is_valid()) return;
|
|
||||||
|
|
||||||
SyncElementAt(index);
|
|
||||||
// Number type information is preserved.
|
|
||||||
// Copies get their number information from their backing element.
|
|
||||||
TypeInfo info;
|
|
||||||
if (!elements_[index].is_copy()) {
|
|
||||||
info = elements_[index].type_info();
|
|
||||||
} else {
|
|
||||||
info = elements_[elements_[index].index()].type_info();
|
|
||||||
}
|
|
||||||
// The element is now in memory. Its copied flag is preserved.
|
|
||||||
FrameElement new_element = FrameElement::MemoryElement(info);
|
|
||||||
if (elements_[index].is_copied()) {
|
|
||||||
new_element.set_copied();
|
|
||||||
}
|
|
||||||
if (elements_[index].is_untagged_int32()) {
|
|
||||||
new_element.set_untagged_int32(true);
|
|
||||||
}
|
|
||||||
if (elements_[index].is_register()) {
|
|
||||||
Unuse(elements_[index].reg());
|
|
||||||
}
|
|
||||||
elements_[index] = new_element;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Clear the dirty bit for the element at a given index.
|
|
||||||
void VirtualFrame::SyncElementAt(int index) {
|
|
||||||
if (index <= stack_pointer_) {
|
|
||||||
if (!elements_[index].is_synced()) SyncElementBelowStackPointer(index);
|
|
||||||
} else if (index == stack_pointer_ + 1) {
|
|
||||||
SyncElementByPushing(index);
|
|
||||||
} else {
|
|
||||||
SyncRange(stack_pointer_ + 1, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Make the type of all elements be MEMORY.
|
|
||||||
void VirtualFrame::SpillAll() {
|
|
||||||
for (int i = 0; i < element_count(); i++) {
|
|
||||||
SpillElementAt(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) {
|
|
||||||
// Perform state changes on this frame that will make merge to the
|
|
||||||
// expected frame simpler or else increase the likelihood that his
|
|
||||||
// frame will match another.
|
|
||||||
for (int i = 0; i < element_count(); i++) {
|
|
||||||
FrameElement source = elements_[i];
|
|
||||||
FrameElement target = expected->elements_[i];
|
|
||||||
|
|
||||||
if (!target.is_valid() ||
|
|
||||||
(target.is_memory() && !source.is_memory() && source.is_synced())) {
|
|
||||||
// No code needs to be generated to invalidate valid elements.
|
|
||||||
// No code needs to be generated to move values to memory if
|
|
||||||
// they are already synced. We perform those moves here, before
|
|
||||||
// merging.
|
|
||||||
if (source.is_register()) {
|
|
||||||
// If the frame is the code generator's current frame, we have
|
|
||||||
// to decrement both the frame-internal and global register
|
|
||||||
// counts.
|
|
||||||
if (cgen()->frame() == this) {
|
|
||||||
Unuse(source.reg());
|
|
||||||
} else {
|
|
||||||
set_register_location(source.reg(), kIllegalIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elements_[i] = target;
|
|
||||||
} else if (target.is_register() && !target.is_synced() &&
|
|
||||||
!source.is_memory()) {
|
|
||||||
// If an element's target is a register that doesn't need to be
|
|
||||||
// synced, and the element is not in memory, then the sync state
|
|
||||||
// of the element is irrelevant. We clear the sync bit.
|
|
||||||
ASSERT(source.is_valid());
|
|
||||||
elements_[i].clear_sync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
|
|
||||||
ASSERT(height() >= dropped_args);
|
|
||||||
ASSERT(height() >= spilled_args);
|
|
||||||
ASSERT(dropped_args <= spilled_args);
|
|
||||||
|
|
||||||
SyncRange(0, element_count() - 1);
|
|
||||||
// Spill registers.
|
|
||||||
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
|
|
||||||
if (is_used(i)) {
|
|
||||||
SpillElementAt(register_location(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spill the arguments.
|
|
||||||
for (int i = element_count() - spilled_args; i < element_count(); i++) {
|
|
||||||
if (!elements_[i].is_memory()) {
|
|
||||||
SpillElementAt(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forget the frame elements that will be popped by the call.
|
|
||||||
Forget(dropped_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::PrepareForReturn() {
|
|
||||||
// Spill all locals. This is necessary to make sure all locals have
|
|
||||||
// the right value when breaking at the return site in the debugger.
|
|
||||||
for (int i = 0; i < expression_base_index(); i++) {
|
|
||||||
SpillElementAt(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VirtualFrame::SetElementAt(int index, Result* value) {
|
|
||||||
int frame_index = element_count() - index - 1;
|
|
||||||
ASSERT(frame_index >= 0);
|
|
||||||
ASSERT(frame_index < element_count());
|
|
||||||
ASSERT(value->is_valid());
|
|
||||||
FrameElement original = elements_[frame_index];
|
|
||||||
|
|
||||||
// Early exit if the element is the same as the one being set.
|
|
||||||
bool same_register = original.is_register()
|
|
||||||
&& value->is_register()
|
|
||||||
&& original.reg().is(value->reg());
|
|
||||||
bool same_constant = original.is_constant()
|
|
||||||
&& value->is_constant()
|
|
||||||
&& original.handle().is_identical_to(value->handle());
|
|
||||||
if (same_register || same_constant) {
|
|
||||||
value->Unuse();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
InvalidateFrameSlotAt(frame_index);
|
|
||||||
|
|
||||||
if (value->is_register()) {
|
|
||||||
if (is_used(value->reg())) {
|
|
||||||
// The register already appears on the frame. Either the existing
|
|
||||||
// register element, or the new element at frame_index, must be made
|
|
||||||
// a copy.
|
|
||||||
int i = register_location(value->reg());
|
|
||||||
|
|
||||||
if (i < frame_index) {
|
|
||||||
// The register FrameElement is lower in the frame than the new copy.
|
|
||||||
elements_[frame_index] = CopyElementAt(i);
|
|
||||||
} else {
|
|
||||||
// There was an early bailout for the case of setting a
|
|
||||||
// register element to itself.
|
|
||||||
ASSERT(i != frame_index);
|
|
||||||
elements_[frame_index] = elements_[i];
|
|
||||||
elements_[i] = CopyElementAt(frame_index);
|
|
||||||
if (elements_[frame_index].is_synced()) {
|
|
||||||
elements_[i].set_sync();
|
|
||||||
}
|
|
||||||
elements_[frame_index].clear_sync();
|
|
||||||
set_register_location(value->reg(), frame_index);
|
|
||||||
for (int j = i + 1; j < element_count(); j++) {
|
|
||||||
if (elements_[j].is_copy() && elements_[j].index() == i) {
|
|
||||||
elements_[j].set_index(frame_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The register value->reg() was not already used on the frame.
|
|
||||||
Use(value->reg(), frame_index);
|
|
||||||
elements_[frame_index] =
|
|
||||||
FrameElement::RegisterElement(value->reg(),
|
|
||||||
FrameElement::NOT_SYNCED,
|
|
||||||
value->type_info());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ASSERT(value->is_constant());
|
|
||||||
elements_[frame_index] =
|
|
||||||
FrameElement::ConstantElement(value->handle(),
|
|
||||||
FrameElement::NOT_SYNCED);
|
|
||||||
}
|
|
||||||
value->Unuse();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Specialization of List::ResizeAdd to non-inlined version for FrameElements.
|
// Specialization of List::ResizeAdd to non-inlined version for FrameElements.
|
||||||
// The function ResizeAdd becomes a real function, whose implementation is the
|
// The function ResizeAdd becomes a real function, whose implementation is the
|
||||||
// inlined ResizeAddInternal.
|
// inlined ResizeAddInternal.
|
||||||
|
@ -139,7 +139,7 @@ class VirtualFrame : public ZoneObject {
|
|||||||
void ForgetElements(int count);
|
void ForgetElements(int count);
|
||||||
|
|
||||||
// Spill all values from the frame to memory.
|
// Spill all values from the frame to memory.
|
||||||
void SpillAll();
|
inline void SpillAll();
|
||||||
|
|
||||||
// Spill all occurrences of a specific register from the frame.
|
// Spill all occurrences of a specific register from the frame.
|
||||||
void Spill(Register reg) {
|
void Spill(Register reg) {
|
||||||
@ -200,7 +200,7 @@ class VirtualFrame : public ZoneObject {
|
|||||||
// Prepare for returning from the frame by spilling locals. This
|
// Prepare for returning from the frame by spilling locals. This
|
||||||
// avoids generating unnecessary merge code when jumping to the
|
// avoids generating unnecessary merge code when jumping to the
|
||||||
// shared return site. Emits code for spills.
|
// shared return site. Emits code for spills.
|
||||||
void PrepareForReturn();
|
inline void PrepareForReturn();
|
||||||
|
|
||||||
// Number of local variables after when we use a loop for allocating.
|
// Number of local variables after when we use a loop for allocating.
|
||||||
static const int kLocalVarBound = 7;
|
static const int kLocalVarBound = 7;
|
||||||
|
@ -276,6 +276,7 @@
|
|||||||
'../../src/execution.h',
|
'../../src/execution.h',
|
||||||
'../../src/factory.cc',
|
'../../src/factory.cc',
|
||||||
'../../src/factory.h',
|
'../../src/factory.h',
|
||||||
|
'../../src/fast-codegen.cc',
|
||||||
'../../src/fast-codegen.h',
|
'../../src/fast-codegen.h',
|
||||||
'../../src/fast-dtoa.cc',
|
'../../src/fast-dtoa.cc',
|
||||||
'../../src/fast-dtoa.h',
|
'../../src/fast-dtoa.h',
|
||||||
@ -309,9 +310,13 @@
|
|||||||
'../../src/ic.h',
|
'../../src/ic.h',
|
||||||
'../../src/interpreter-irregexp.cc',
|
'../../src/interpreter-irregexp.cc',
|
||||||
'../../src/interpreter-irregexp.h',
|
'../../src/interpreter-irregexp.h',
|
||||||
|
'../../src/jump-target-heavy-inl.h',
|
||||||
|
'../../src/jump-target-heavy.cc',
|
||||||
|
'../../src/jump-target-inl.h',
|
||||||
|
'../../src/jump-target-light-inl.h',
|
||||||
|
'../../src/jump-target-light.cc',
|
||||||
'../../src/jump-target.cc',
|
'../../src/jump-target.cc',
|
||||||
'../../src/jump-target.h',
|
'../../src/jump-target.h',
|
||||||
'../../src/jump-target-inl.h',
|
|
||||||
'../../src/jsregexp.cc',
|
'../../src/jsregexp.cc',
|
||||||
'../../src/jsregexp.h',
|
'../../src/jsregexp.h',
|
||||||
'../../src/list-inl.h',
|
'../../src/list-inl.h',
|
||||||
@ -403,7 +408,11 @@
|
|||||||
'../../src/variables.h',
|
'../../src/variables.h',
|
||||||
'../../src/version.cc',
|
'../../src/version.cc',
|
||||||
'../../src/version.h',
|
'../../src/version.h',
|
||||||
|
'../../src/virtual-frame-heavy-inl.h',
|
||||||
|
'../../src/virtual-frame-heavy.cc',
|
||||||
'../../src/virtual-frame-inl.h',
|
'../../src/virtual-frame-inl.h',
|
||||||
|
'../../src/virtual-frame-light-inl.h',
|
||||||
|
'../../src/virtual-frame-light.cc',
|
||||||
'../../src/virtual-frame.cc',
|
'../../src/virtual-frame.cc',
|
||||||
'../../src/virtual-frame.h',
|
'../../src/virtual-frame.h',
|
||||||
'../../src/zone-inl.h',
|
'../../src/zone-inl.h',
|
||||||
@ -416,7 +425,10 @@
|
|||||||
'../../src/arm',
|
'../../src/arm',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
'../../src/fast-codegen.cc',
|
'../../src/jump-target-light-inl.h',
|
||||||
|
'../../src/jump-target-light.cc',
|
||||||
|
'../../src/virtual-frame-light-inl.h',
|
||||||
|
'../../src/virtual-frame-light.cc',
|
||||||
'../../src/arm/assembler-arm-inl.h',
|
'../../src/arm/assembler-arm-inl.h',
|
||||||
'../../src/arm/assembler-arm.cc',
|
'../../src/arm/assembler-arm.cc',
|
||||||
'../../src/arm/assembler-arm.h',
|
'../../src/arm/assembler-arm.h',
|
||||||
@ -458,6 +470,10 @@
|
|||||||
'../../src/ia32',
|
'../../src/ia32',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'../../src/jump-target-heavy-inl.h',
|
||||||
|
'../../src/jump-target-heavy.cc',
|
||||||
|
'../../src/virtual-frame-heavy-inl.h',
|
||||||
|
'../../src/virtual-frame-heavy.cc',
|
||||||
'../../src/ia32/assembler-ia32-inl.h',
|
'../../src/ia32/assembler-ia32-inl.h',
|
||||||
'../../src/ia32/assembler-ia32.cc',
|
'../../src/ia32/assembler-ia32.cc',
|
||||||
'../../src/ia32/assembler-ia32.h',
|
'../../src/ia32/assembler-ia32.h',
|
||||||
@ -489,7 +505,10 @@
|
|||||||
'../../src/x64',
|
'../../src/x64',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
'../../src/fast-codegen.cc',
|
'../../src/jump-target-heavy-inl.h',
|
||||||
|
'../../src/jump-target-heavy.cc',
|
||||||
|
'../../src/virtual-frame-heavy-inl.h',
|
||||||
|
'../../src/virtual-frame-heavy.cc',
|
||||||
'../../src/x64/assembler-x64-inl.h',
|
'../../src/x64/assembler-x64-inl.h',
|
||||||
'../../src/x64/assembler-x64.cc',
|
'../../src/x64/assembler-x64.cc',
|
||||||
'../../src/x64/assembler-x64.h',
|
'../../src/x64/assembler-x64.h',
|
||||||
|
@ -27,16 +27,20 @@
|
|||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
58950D5E0F55519800F3E8BA /* jump-target.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D500F55514900F3E8BA /* jump-target.cc */; };
|
58950D5E0F55519800F3E8BA /* jump-target.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D500F55514900F3E8BA /* jump-target.cc */; };
|
||||||
58950D5F0F55519D00F3E8BA /* jump-target-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */; };
|
58950D5F0F55519D00F3E8BA /* jump-target-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */; };
|
||||||
|
58950D5F0F55519D00F3E8BA /* jump-target-heavy.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4F0F55514900F3E8BA /* jump-target-heavy.cc */; };
|
||||||
58950D600F5551A300F3E8BA /* jump-target.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D500F55514900F3E8BA /* jump-target.cc */; };
|
58950D600F5551A300F3E8BA /* jump-target.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D500F55514900F3E8BA /* jump-target.cc */; };
|
||||||
58950D610F5551A400F3E8BA /* jump-target-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4E0F55514900F3E8BA /* jump-target-arm.cc */; };
|
58950D610F5551A400F3E8BA /* jump-target-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4E0F55514900F3E8BA /* jump-target-arm.cc */; };
|
||||||
|
58950D610F5551A400F3E8BA /* jump-target-light.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4E0F55514900F3E8BA /* jump-target-light.cc */; };
|
||||||
58950D620F5551AF00F3E8BA /* register-allocator-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D530F55514900F3E8BA /* register-allocator-ia32.cc */; };
|
58950D620F5551AF00F3E8BA /* register-allocator-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D530F55514900F3E8BA /* register-allocator-ia32.cc */; };
|
||||||
58950D630F5551AF00F3E8BA /* register-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D540F55514900F3E8BA /* register-allocator.cc */; };
|
58950D630F5551AF00F3E8BA /* register-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D540F55514900F3E8BA /* register-allocator.cc */; };
|
||||||
58950D640F5551B500F3E8BA /* register-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D540F55514900F3E8BA /* register-allocator.cc */; };
|
58950D640F5551B500F3E8BA /* register-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D540F55514900F3E8BA /* register-allocator.cc */; };
|
||||||
58950D650F5551B600F3E8BA /* register-allocator-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D520F55514900F3E8BA /* register-allocator-arm.cc */; };
|
58950D650F5551B600F3E8BA /* register-allocator-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D520F55514900F3E8BA /* register-allocator-arm.cc */; };
|
||||||
58950D660F5551C200F3E8BA /* virtual-frame.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D5A0F55514900F3E8BA /* virtual-frame.cc */; };
|
58950D660F5551C200F3E8BA /* virtual-frame.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D5A0F55514900F3E8BA /* virtual-frame.cc */; };
|
||||||
58950D670F5551C400F3E8BA /* virtual-frame-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */; };
|
58950D670F5551C400F3E8BA /* virtual-frame-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */; };
|
||||||
|
58950D670F5551C400F3E8BA /* virtual-frame-heavy.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D580F55514900F3E8BA /* virtual-frame-heavy.cc */; };
|
||||||
58950D680F5551CB00F3E8BA /* virtual-frame.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D5A0F55514900F3E8BA /* virtual-frame.cc */; };
|
58950D680F5551CB00F3E8BA /* virtual-frame.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D5A0F55514900F3E8BA /* virtual-frame.cc */; };
|
||||||
58950D690F5551CE00F3E8BA /* virtual-frame-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D560F55514900F3E8BA /* virtual-frame-arm.cc */; };
|
58950D690F5551CE00F3E8BA /* virtual-frame-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D560F55514900F3E8BA /* virtual-frame-arm.cc */; };
|
||||||
|
58950D690F5551CE00F3E8BA /* virtual-frame-light.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D560F55514900F3E8BA /* virtual-frame-light.cc */; };
|
||||||
8900116C0E71CA2300F91F35 /* libraries.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8900116B0E71CA2300F91F35 /* libraries.cc */; };
|
8900116C0E71CA2300F91F35 /* libraries.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8900116B0E71CA2300F91F35 /* libraries.cc */; };
|
||||||
890A13FE0EE9C47F00E49346 /* interpreter-irregexp.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C660EE4665300B48DEB /* interpreter-irregexp.cc */; };
|
890A13FE0EE9C47F00E49346 /* interpreter-irregexp.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C660EE4665300B48DEB /* interpreter-irregexp.cc */; };
|
||||||
890A14010EE9C4B000E49346 /* regexp-macro-assembler-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C700EE466D000B48DEB /* regexp-macro-assembler-arm.cc */; };
|
890A14010EE9C4B000E49346 /* regexp-macro-assembler-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C700EE466D000B48DEB /* regexp-macro-assembler-arm.cc */; };
|
||||||
@ -291,7 +295,9 @@
|
|||||||
22A76C900FF259E600FDC694 /* log-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "log-inl.h"; sourceTree = "<group>"; };
|
22A76C900FF259E600FDC694 /* log-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "log-inl.h"; sourceTree = "<group>"; };
|
||||||
58242A1E0FA1F14D00BD6F59 /* json-delay.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "json-delay.js"; sourceTree = "<group>"; };
|
58242A1E0FA1F14D00BD6F59 /* json-delay.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "json-delay.js"; sourceTree = "<group>"; };
|
||||||
58950D4E0F55514900F3E8BA /* jump-target-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-arm.cc"; path = "arm/jump-target-arm.cc"; sourceTree = "<group>"; };
|
58950D4E0F55514900F3E8BA /* jump-target-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-arm.cc"; path = "arm/jump-target-arm.cc"; sourceTree = "<group>"; };
|
||||||
|
58950D4E0F55514900F3E8BA /* jump-target-light.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-light.cc"; path = "jump-target-light.cc"; sourceTree = "<group>"; };
|
||||||
58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-ia32.cc"; path = "ia32/jump-target-ia32.cc"; sourceTree = "<group>"; };
|
58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-ia32.cc"; path = "ia32/jump-target-ia32.cc"; sourceTree = "<group>"; };
|
||||||
|
58950D4F0F55514900F3E8BA /* jump-target-heavy.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-heavy.cc"; path = "jump-target-heavy.cc"; sourceTree = "<group>"; };
|
||||||
58950D500F55514900F3E8BA /* jump-target.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "jump-target.cc"; sourceTree = "<group>"; };
|
58950D500F55514900F3E8BA /* jump-target.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "jump-target.cc"; sourceTree = "<group>"; };
|
||||||
58950D510F55514900F3E8BA /* jump-target.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target.h"; sourceTree = "<group>"; };
|
58950D510F55514900F3E8BA /* jump-target.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target.h"; sourceTree = "<group>"; };
|
||||||
58950D520F55514900F3E8BA /* register-allocator-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "register-allocator-arm.cc"; path = "arm/register-allocator-arm.cc"; sourceTree = "<group>"; };
|
58950D520F55514900F3E8BA /* register-allocator-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "register-allocator-arm.cc"; path = "arm/register-allocator-arm.cc"; sourceTree = "<group>"; };
|
||||||
@ -299,8 +305,10 @@
|
|||||||
58950D540F55514900F3E8BA /* register-allocator.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "register-allocator.cc"; sourceTree = "<group>"; };
|
58950D540F55514900F3E8BA /* register-allocator.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "register-allocator.cc"; sourceTree = "<group>"; };
|
||||||
58950D550F55514900F3E8BA /* register-allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "register-allocator.h"; sourceTree = "<group>"; };
|
58950D550F55514900F3E8BA /* register-allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "register-allocator.h"; sourceTree = "<group>"; };
|
||||||
58950D560F55514900F3E8BA /* virtual-frame-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-arm.cc"; path = "arm/virtual-frame-arm.cc"; sourceTree = "<group>"; };
|
58950D560F55514900F3E8BA /* virtual-frame-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-arm.cc"; path = "arm/virtual-frame-arm.cc"; sourceTree = "<group>"; };
|
||||||
|
58950D560F55514900F3E8BA /* virtual-frame-light.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-light.cc"; path = "virtual-frame-light.cc"; sourceTree = "<group>"; };
|
||||||
58950D570F55514900F3E8BA /* virtual-frame-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "virtual-frame-arm.h"; path = "arm/virtual-frame-arm.h"; sourceTree = "<group>"; };
|
58950D570F55514900F3E8BA /* virtual-frame-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "virtual-frame-arm.h"; path = "arm/virtual-frame-arm.h"; sourceTree = "<group>"; };
|
||||||
58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-ia32.cc"; path = "ia32/virtual-frame-ia32.cc"; sourceTree = "<group>"; };
|
58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-ia32.cc"; path = "ia32/virtual-frame-ia32.cc"; sourceTree = "<group>"; };
|
||||||
|
58950D580F55514900F3E8BA /* virtual-frame-heavy.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-heavy.cc"; path = "virtual-frame-heavy.cc"; sourceTree = "<group>"; };
|
||||||
58950D590F55514900F3E8BA /* virtual-frame-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "virtual-frame-ia32.h"; path = "ia32/virtual-frame-ia32.h"; sourceTree = "<group>"; };
|
58950D590F55514900F3E8BA /* virtual-frame-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "virtual-frame-ia32.h"; path = "ia32/virtual-frame-ia32.h"; sourceTree = "<group>"; };
|
||||||
58950D5A0F55514900F3E8BA /* virtual-frame.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "virtual-frame.cc"; sourceTree = "<group>"; };
|
58950D5A0F55514900F3E8BA /* virtual-frame.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "virtual-frame.cc"; sourceTree = "<group>"; };
|
||||||
58950D5B0F55514900F3E8BA /* virtual-frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "virtual-frame.h"; sourceTree = "<group>"; };
|
58950D5B0F55514900F3E8BA /* virtual-frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "virtual-frame.h"; sourceTree = "<group>"; };
|
||||||
@ -321,6 +329,8 @@
|
|||||||
8956B6CD0F5D86570033B5A2 /* debug-agent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "debug-agent.cc"; sourceTree = "<group>"; };
|
8956B6CD0F5D86570033B5A2 /* debug-agent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "debug-agent.cc"; sourceTree = "<group>"; };
|
||||||
8956B6CE0F5D86570033B5A2 /* debug-agent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "debug-agent.h"; sourceTree = "<group>"; };
|
8956B6CE0F5D86570033B5A2 /* debug-agent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "debug-agent.h"; sourceTree = "<group>"; };
|
||||||
895FA720107FFB15006F39D4 /* jump-target-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target-inl.h"; sourceTree = "<group>"; };
|
895FA720107FFB15006F39D4 /* jump-target-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target-inl.h"; sourceTree = "<group>"; };
|
||||||
|
895FA720107FFB15006F39D4 /* jump-target-light-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target-light-inl.h"; sourceTree = "<group>"; };
|
||||||
|
895FA720107FFB15006F39D4 /* jump-target-heavy-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target-heavy-inl.h"; sourceTree = "<group>"; };
|
||||||
895FA725107FFB57006F39D4 /* codegen-ia32-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "codegen-ia32-inl.h"; path = "ia32/codegen-ia32-inl.h"; sourceTree = "<group>"; };
|
895FA725107FFB57006F39D4 /* codegen-ia32-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "codegen-ia32-inl.h"; path = "ia32/codegen-ia32-inl.h"; sourceTree = "<group>"; };
|
||||||
895FA72A107FFB85006F39D4 /* register-allocator-ia32-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "register-allocator-ia32-inl.h"; path = "ia32/register-allocator-ia32-inl.h"; sourceTree = "<group>"; };
|
895FA72A107FFB85006F39D4 /* register-allocator-ia32-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "register-allocator-ia32-inl.h"; path = "ia32/register-allocator-ia32-inl.h"; sourceTree = "<group>"; };
|
||||||
895FA72B107FFB85006F39D4 /* register-allocator-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "register-allocator-ia32.h"; path = "ia32/register-allocator-ia32.h"; sourceTree = "<group>"; };
|
895FA72B107FFB85006F39D4 /* register-allocator-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "register-allocator-ia32.h"; path = "ia32/register-allocator-ia32.h"; sourceTree = "<group>"; };
|
||||||
@ -785,8 +795,12 @@
|
|||||||
897FF14E0E719B8F00D62E90 /* jsregexp.cc */,
|
897FF14E0E719B8F00D62E90 /* jsregexp.cc */,
|
||||||
897FF14F0E719B8F00D62E90 /* jsregexp.h */,
|
897FF14F0E719B8F00D62E90 /* jsregexp.h */,
|
||||||
895FA720107FFB15006F39D4 /* jump-target-inl.h */,
|
895FA720107FFB15006F39D4 /* jump-target-inl.h */,
|
||||||
|
895FA720107FFB15006F39D4 /* jump-target-heavy-inl.h */,
|
||||||
|
895FA720107FFB15006F39D4 /* jump-target-light-inl.h */,
|
||||||
58950D4E0F55514900F3E8BA /* jump-target-arm.cc */,
|
58950D4E0F55514900F3E8BA /* jump-target-arm.cc */,
|
||||||
|
58950D4E0F55514900F3E8BA /* jump-target-light.cc */,
|
||||||
58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */,
|
58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */,
|
||||||
|
58950D4F0F55514900F3E8BA /* jump-target-heavy.cc */,
|
||||||
58950D500F55514900F3E8BA /* jump-target.cc */,
|
58950D500F55514900F3E8BA /* jump-target.cc */,
|
||||||
58950D510F55514900F3E8BA /* jump-target.h */,
|
58950D510F55514900F3E8BA /* jump-target.h */,
|
||||||
897FF1500E719B8F00D62E90 /* list-inl.h */,
|
897FF1500E719B8F00D62E90 /* list-inl.h */,
|
||||||
@ -905,8 +919,10 @@
|
|||||||
897FF32F0FAA0ED200136CF6 /* version.cc */,
|
897FF32F0FAA0ED200136CF6 /* version.cc */,
|
||||||
897FF3300FAA0ED200136CF6 /* version.h */,
|
897FF3300FAA0ED200136CF6 /* version.h */,
|
||||||
58950D560F55514900F3E8BA /* virtual-frame-arm.cc */,
|
58950D560F55514900F3E8BA /* virtual-frame-arm.cc */,
|
||||||
|
58950D560F55514900F3E8BA /* virtual-frame-light.cc */,
|
||||||
58950D570F55514900F3E8BA /* virtual-frame-arm.h */,
|
58950D570F55514900F3E8BA /* virtual-frame-arm.h */,
|
||||||
58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */,
|
58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */,
|
||||||
|
58950D580F55514900F3E8BA /* virtual-frame-heavy.cc */,
|
||||||
58950D590F55514900F3E8BA /* virtual-frame-ia32.h */,
|
58950D590F55514900F3E8BA /* virtual-frame-ia32.h */,
|
||||||
58950D5A0F55514900F3E8BA /* virtual-frame.cc */,
|
58950D5A0F55514900F3E8BA /* virtual-frame.cc */,
|
||||||
58950D5B0F55514900F3E8BA /* virtual-frame.h */,
|
58950D5B0F55514900F3E8BA /* virtual-frame.h */,
|
||||||
@ -1213,6 +1229,7 @@
|
|||||||
89A88E0E0E71A66F0043BA31 /* jsregexp.cc in Sources */,
|
89A88E0E0E71A66F0043BA31 /* jsregexp.cc in Sources */,
|
||||||
58950D5E0F55519800F3E8BA /* jump-target.cc in Sources */,
|
58950D5E0F55519800F3E8BA /* jump-target.cc in Sources */,
|
||||||
58950D5F0F55519D00F3E8BA /* jump-target-ia32.cc in Sources */,
|
58950D5F0F55519D00F3E8BA /* jump-target-ia32.cc in Sources */,
|
||||||
|
58950D5F0F55519D00F3E8BA /* jump-target-heavy.cc in Sources */,
|
||||||
8900116C0E71CA2300F91F35 /* libraries.cc in Sources */,
|
8900116C0E71CA2300F91F35 /* libraries.cc in Sources */,
|
||||||
89A88E0F0E71A6740043BA31 /* log.cc in Sources */,
|
89A88E0F0E71A6740043BA31 /* log.cc in Sources */,
|
||||||
89A88E100E71A6770043BA31 /* macro-assembler-ia32.cc in Sources */,
|
89A88E100E71A6770043BA31 /* macro-assembler-ia32.cc in Sources */,
|
||||||
@ -1256,6 +1273,7 @@
|
|||||||
89A88E2D0E71A6D50043BA31 /* variables.cc in Sources */,
|
89A88E2D0E71A6D50043BA31 /* variables.cc in Sources */,
|
||||||
89B933AF0FAA0F9600201304 /* version.cc in Sources */,
|
89B933AF0FAA0F9600201304 /* version.cc in Sources */,
|
||||||
58950D660F5551C200F3E8BA /* virtual-frame.cc in Sources */,
|
58950D660F5551C200F3E8BA /* virtual-frame.cc in Sources */,
|
||||||
|
58950D660F5551C200F3E8BA /* virtual-frame-heavy.cc in Sources */,
|
||||||
58950D670F5551C400F3E8BA /* virtual-frame-ia32.cc in Sources */,
|
58950D670F5551C400F3E8BA /* virtual-frame-ia32.cc in Sources */,
|
||||||
89A88E2E0E71A6D60043BA31 /* zone.cc in Sources */,
|
89A88E2E0E71A6D60043BA31 /* zone.cc in Sources */,
|
||||||
9F4B7B890FCC877A00DC4117 /* log-utils.cc in Sources */,
|
9F4B7B890FCC877A00DC4117 /* log-utils.cc in Sources */,
|
||||||
@ -1324,6 +1342,7 @@
|
|||||||
89F23C610E78D5B2006B2466 /* jsregexp.cc in Sources */,
|
89F23C610E78D5B2006B2466 /* jsregexp.cc in Sources */,
|
||||||
58950D600F5551A300F3E8BA /* jump-target.cc in Sources */,
|
58950D600F5551A300F3E8BA /* jump-target.cc in Sources */,
|
||||||
58950D610F5551A400F3E8BA /* jump-target-arm.cc in Sources */,
|
58950D610F5551A400F3E8BA /* jump-target-arm.cc in Sources */,
|
||||||
|
58950D610F5551A400F3E8BA /* jump-target-light.cc in Sources */,
|
||||||
89F23C620E78D5B2006B2466 /* libraries.cc in Sources */,
|
89F23C620E78D5B2006B2466 /* libraries.cc in Sources */,
|
||||||
89F23C630E78D5B2006B2466 /* log.cc in Sources */,
|
89F23C630E78D5B2006B2466 /* log.cc in Sources */,
|
||||||
89F23C9E0E78D5FD006B2466 /* macro-assembler-arm.cc in Sources */,
|
89F23C9E0E78D5FD006B2466 /* macro-assembler-arm.cc in Sources */,
|
||||||
@ -1368,6 +1387,7 @@
|
|||||||
89F23C810E78D5B2006B2466 /* variables.cc in Sources */,
|
89F23C810E78D5B2006B2466 /* variables.cc in Sources */,
|
||||||
89B933B00FAA0F9D00201304 /* version.cc in Sources */,
|
89B933B00FAA0F9D00201304 /* version.cc in Sources */,
|
||||||
58950D680F5551CB00F3E8BA /* virtual-frame.cc in Sources */,
|
58950D680F5551CB00F3E8BA /* virtual-frame.cc in Sources */,
|
||||||
|
58950D680F5551CB00F3E8BA /* virtual-frame-light.cc in Sources */,
|
||||||
58950D690F5551CE00F3E8BA /* virtual-frame-arm.cc in Sources */,
|
58950D690F5551CE00F3E8BA /* virtual-frame-arm.cc in Sources */,
|
||||||
89F23C820E78D5B2006B2466 /* zone.cc in Sources */,
|
89F23C820E78D5B2006B2466 /* zone.cc in Sources */,
|
||||||
9F4B7B8A0FCC877A00DC4117 /* log-utils.cc in Sources */,
|
9F4B7B8A0FCC877A00DC4117 /* log-utils.cc in Sources */,
|
||||||
|
@ -600,6 +600,10 @@
|
|||||||
RelativePath="..\..\src\jump-target-inl.h"
|
RelativePath="..\..\src\jump-target-inl.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\jump-target-heavy-inl.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\jump-target.cc"
|
RelativePath="..\..\src\jump-target.cc"
|
||||||
>
|
>
|
||||||
@ -608,6 +612,10 @@
|
|||||||
RelativePath="..\..\src\ia32\jump-target-ia32.cc"
|
RelativePath="..\..\src\ia32\jump-target-ia32.cc"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\jump-target-heavy.cc"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\jsregexp.cc"
|
RelativePath="..\..\src\jsregexp.cc"
|
||||||
>
|
>
|
||||||
@ -996,6 +1004,10 @@
|
|||||||
RelativePath="..\..\src\virtual-frame-inl.h"
|
RelativePath="..\..\src\virtual-frame-inl.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\virtual-frame-heavy-inl.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\virtual-frame.h"
|
RelativePath="..\..\src\virtual-frame.h"
|
||||||
>
|
>
|
||||||
@ -1012,6 +1024,10 @@
|
|||||||
RelativePath="..\..\src\ia32\virtual-frame-ia32.cc"
|
RelativePath="..\..\src\ia32\virtual-frame-ia32.cc"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\virtual-frame-heavy.cc"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\zone-inl.h"
|
RelativePath="..\..\src\zone-inl.h"
|
||||||
>
|
>
|
||||||
|
@ -580,6 +580,14 @@
|
|||||||
RelativePath="..\..\src\jump-target.h"
|
RelativePath="..\..\src\jump-target.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\jump-target-inl.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\jump-target-light-inl.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\jump-target.cc"
|
RelativePath="..\..\src\jump-target.cc"
|
||||||
>
|
>
|
||||||
@ -588,6 +596,10 @@
|
|||||||
RelativePath="..\..\src\arm\jump-target-arm.cc"
|
RelativePath="..\..\src\arm\jump-target-arm.cc"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\jump-target-light.cc"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\jsregexp.cc"
|
RelativePath="..\..\src\jsregexp.cc"
|
||||||
>
|
>
|
||||||
@ -984,6 +996,10 @@
|
|||||||
RelativePath="..\..\src\virtual-frame-inl.h"
|
RelativePath="..\..\src\virtual-frame-inl.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\virtual-frame-light-inl.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\virtual-frame.h"
|
RelativePath="..\..\src\virtual-frame.h"
|
||||||
>
|
>
|
||||||
@ -1000,6 +1016,10 @@
|
|||||||
RelativePath="..\..\src\arm\virtual-frame-arm.cc"
|
RelativePath="..\..\src\arm\virtual-frame-arm.cc"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\virtual-frame-light.cc"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\zone-inl.h"
|
RelativePath="..\..\src\zone-inl.h"
|
||||||
>
|
>
|
||||||
|
@ -577,6 +577,10 @@
|
|||||||
RelativePath="..\..\src\jump-target-inl.h"
|
RelativePath="..\..\src\jump-target-inl.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\jump-target-heavy-inl.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\jump-target.cc"
|
RelativePath="..\..\src\jump-target.cc"
|
||||||
>
|
>
|
||||||
@ -585,6 +589,10 @@
|
|||||||
RelativePath="..\..\src\x64\jump-target-x64.cc"
|
RelativePath="..\..\src\x64\jump-target-x64.cc"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\jump-target-heavy.cc"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\jsregexp.cc"
|
RelativePath="..\..\src\jsregexp.cc"
|
||||||
>
|
>
|
||||||
@ -973,6 +981,10 @@
|
|||||||
RelativePath="..\..\src\virtual-frame-inl.h"
|
RelativePath="..\..\src\virtual-frame-inl.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\virtual-frame-heavy-inl.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\virtual-frame.h"
|
RelativePath="..\..\src\virtual-frame.h"
|
||||||
>
|
>
|
||||||
@ -989,6 +1001,10 @@
|
|||||||
RelativePath="..\..\src\x64\virtual-frame-x64.cc"
|
RelativePath="..\..\src\x64\virtual-frame-x64.cc"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\virtual-frame-heavy.cc"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\zone-inl.h"
|
RelativePath="..\..\src\zone-inl.h"
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user