|
|
|
// Copyright 2009 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_FRAME_ELEMENT_H_
|
|
|
|
#define V8_FRAME_ELEMENT_H_
|
|
|
|
|
|
|
|
#include "register-allocator-inl.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
// Virtual frame elements
|
|
|
|
//
|
|
|
|
// The internal elements of the virtual frames. There are several kinds of
|
|
|
|
// elements:
|
|
|
|
// * Invalid: elements that are uninitialized or not actually part
|
|
|
|
// of the virtual frame. They should not be read.
|
|
|
|
// * Memory: an element that resides in the actual frame. Its address is
|
|
|
|
// given by its position in the virtual frame.
|
|
|
|
// * Register: an element that resides in a register.
|
|
|
|
// * Constant: an element whose value is known at compile time.
|
|
|
|
|
|
|
|
class FrameElement BASE_EMBEDDED {
|
|
|
|
public:
|
|
|
|
enum SyncFlag {
|
|
|
|
NOT_SYNCED,
|
|
|
|
SYNCED
|
|
|
|
};
|
|
|
|
|
|
|
|
// The default constructor creates an invalid frame element.
|
|
|
|
FrameElement() {
|
|
|
|
value_ = TypeField::encode(INVALID)
|
|
|
|
| CopiedField::encode(false)
|
|
|
|
| SyncedField::encode(false)
|
|
|
|
| DataField::encode(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Factory function to construct an invalid frame element.
|
|
|
|
static FrameElement InvalidElement() {
|
|
|
|
FrameElement result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Factory function to construct an in-memory frame element.
|
|
|
|
static FrameElement MemoryElement() {
|
|
|
|
FrameElement result(MEMORY, no_reg, SYNCED);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Factory function to construct an in-register frame element.
|
|
|
|
static FrameElement RegisterElement(Register reg,
|
|
|
|
SyncFlag is_synced) {
|
|
|
|
return FrameElement(REGISTER, reg, is_synced);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Factory function to construct a frame element whose value is known at
|
|
|
|
// compile time.
|
|
|
|
static FrameElement ConstantElement(Handle<Object> value,
|
|
|
|
SyncFlag is_synced) {
|
|
|
|
FrameElement result(value, is_synced);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Static indirection table for handles to constants. If a frame
|
|
|
|
// element represents a constant, the data contains an index into
|
|
|
|
// this table of handles to the actual constants.
|
|
|
|
typedef ZoneList<Handle<Object> > ZoneObjectList;
|
|
|
|
|
|
|
|
static ZoneObjectList* ConstantList() {
|
|
|
|
static ZoneObjectList list(10);
|
|
|
|
return &list;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear the constants indirection table.
|
|
|
|
static void ClearConstantList() {
|
|
|
|
ConstantList()->Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_synced() const { return SyncedField::decode(value_); }
|
|
|
|
|
|
|
|
void set_sync() {
|
|
|
|
ASSERT(type() != MEMORY);
|
|
|
|
value_ = value_ | SyncedField::encode(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear_sync() {
|
|
|
|
ASSERT(type() != MEMORY);
|
|
|
|
value_ = value_ & ~SyncedField::mask();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_valid() const { return type() != INVALID; }
|
|
|
|
bool is_memory() const { return type() == MEMORY; }
|
|
|
|
bool is_register() const { return type() == REGISTER; }
|
|
|
|
bool is_constant() const { return type() == CONSTANT; }
|
|
|
|
bool is_copy() const { return type() == COPY; }
|
|
|
|
|
|
|
|
bool is_copied() const { return CopiedField::decode(value_); }
|
|
|
|
void set_copied() { value_ = value_ | CopiedField::encode(true); }
|
|
|
|
void clear_copied() { value_ = value_ & ~CopiedField::mask(); }
|
|
|
|
|
|
|
|
Register reg() const {
|
|
|
|
ASSERT(is_register());
|
|
|
|
uint32_t reg = DataField::decode(value_);
|
|
|
|
Register result;
|
|
|
|
result.code_ = reg;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<Object> handle() const {
|
|
|
|
ASSERT(is_constant());
|
|
|
|
return ConstantList()->at(DataField::decode(value_));
|
|
|
|
}
|
|
|
|
|
|
|
|
int index() const {
|
|
|
|
ASSERT(is_copy());
|
|
|
|
return DataField::decode(value_);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Equals(FrameElement other) {
|
|
|
|
uint32_t masked_difference = (value_ ^ other.value_) & ~CopiedField::mask();
|
|
|
|
if (!masked_difference) {
|
|
|
|
// The elements are equal if they agree exactly except on copied field.
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
// If two constants have the same value, and agree otherwise, return true.
|
|
|
|
return !(masked_difference & ~DataField::mask()) &&
|
|
|
|
is_constant() &&
|
|
|
|
handle().is_identical_to(other.handle());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test if two FrameElements refer to the same memory or register location.
|
|
|
|
bool SameLocation(FrameElement* other) {
|
|
|
|
if (type() == other->type()) {
|
|
|
|
if (value_ == other->value_) return true;
|
|
|
|
if (is_constant() && handle().is_identical_to(other->handle())) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Given a pair of non-null frame element pointers, return one of them
|
|
|
|
// as an entry frame candidate or null if they are incompatible.
|
|
|
|
FrameElement* Combine(FrameElement* other) {
|
|
|
|
// If either is invalid, the result is.
|
|
|
|
if (!is_valid()) return this;
|
|
|
|
if (!other->is_valid()) return other;
|
|
|
|
|
|
|
|
if (!SameLocation(other)) return NULL;
|
|
|
|
// If either is unsynced, the result is.
|
|
|
|
FrameElement* result = is_synced() ? other : this;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
enum Type {
|
|
|
|
INVALID,
|
|
|
|
MEMORY,
|
|
|
|
REGISTER,
|
|
|
|
CONSTANT,
|
|
|
|
COPY
|
|
|
|
};
|
|
|
|
|
|
|
|
// Used to construct memory and register elements.
|
|
|
|
FrameElement(Type type, Register reg, SyncFlag is_synced) {
|
|
|
|
value_ = TypeField::encode(type)
|
|
|
|
| CopiedField::encode(false)
|
|
|
|
| SyncedField::encode(is_synced != NOT_SYNCED)
|
|
|
|
| DataField::encode(reg.code_ > 0 ? reg.code_ : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Used to construct constant elements.
|
|
|
|
FrameElement(Handle<Object> value, SyncFlag is_synced) {
|
|
|
|
value_ = TypeField::encode(CONSTANT)
|
|
|
|
| CopiedField::encode(false)
|
|
|
|
| SyncedField::encode(is_synced != NOT_SYNCED)
|
|
|
|
| DataField::encode(ConstantList()->length());
|
|
|
|
ConstantList()->Add(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
Type type() const { return TypeField::decode(value_); }
|
|
|
|
void set_type(Type type) {
|
|
|
|
value_ = value_ & ~TypeField::mask();
|
|
|
|
value_ = value_ | TypeField::encode(type);
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_index(int new_index) {
|
|
|
|
ASSERT(is_copy());
|
|
|
|
value_ = value_ & ~DataField::mask();
|
|
|
|
value_ = value_ | DataField::encode(new_index);
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_reg(Register new_reg) {
|
|
|
|
ASSERT(is_register());
|
|
|
|
value_ = value_ & ~DataField::mask();
|
|
|
|
value_ = value_ | DataField::encode(new_reg.code_);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode type, copied, synced and data in one 32 bit integer.
|
|
|
|
uint32_t value_;
|
|
|
|
|
|
|
|
class TypeField: public BitField<Type, 0, 3> {};
|
|
|
|
class CopiedField: public BitField<uint32_t, 3, 1> {};
|
|
|
|
class SyncedField: public BitField<uint32_t, 4, 1> {};
|
|
|
|
class DataField: public BitField<uint32_t, 5, 32 - 6> {};
|
|
|
|
|
|
|
|
friend class VirtualFrame;
|
|
|
|
};
|
|
|
|
|
|
|
|
} } // namespace v8::internal
|
|
|
|
|
|
|
|
#endif // V8_FRAME_ELEMENT_H_
|