blob: 92e4f81c01cb1e6b5f28eee3e5ce74aadd6d18a3 [file] [log] [blame]
rossberg@chromium.org994edf62012-02-06 10:12:55 +00001// Copyright 2012 the V8 project authors. All rights reserved.
danno@chromium.orgc612e022011-11-10 11:38:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_PROPERTY_DETAILS_H_
29#define V8_PROPERTY_DETAILS_H_
30
31#include "../include/v8.h"
32#include "allocation.h"
33#include "utils.h"
34
35// Ecma-262 3rd 8.6.1
36enum PropertyAttributes {
37 NONE = v8::None,
38 READ_ONLY = v8::ReadOnly,
39 DONT_ENUM = v8::DontEnum,
40 DONT_DELETE = v8::DontDelete,
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000041
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000042 SEALED = DONT_DELETE,
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000043 FROZEN = SEALED | READ_ONLY,
44
ulan@chromium.org750145a2013-03-07 15:14:13 +000045 SYMBOLIC = 8, // Used to filter symbol names
46 DONT_SHOW = DONT_ENUM | SYMBOLIC,
danno@chromium.orgc612e022011-11-10 11:38:15 +000047 ABSENT = 16 // Used in runtime to indicate a property is absent.
48 // ABSENT can never be stored in or returned from a descriptor's attributes
49 // bitfield. It is only used as a return value meaning the attributes of
50 // a non-existent property.
51};
52
53
54namespace v8 {
55namespace internal {
56
57class Smi;
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000058class Type;
59class TypeInfo;
danno@chromium.orgc612e022011-11-10 11:38:15 +000060
61// Type of properties.
62// Order of properties is significant.
63// Must fit in the BitField PropertyDetails::TypeField.
64// A copy of this is in mirror-debugger.js.
65enum PropertyType {
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000066 // Only in slow mode.
67 NORMAL = 0,
68 // Only in fast mode.
69 FIELD = 1,
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +000070 CONSTANT = 2,
danno@chromium.orgc612e022011-11-10 11:38:15 +000071 CALLBACKS = 3,
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000072 // Only in lookup results, not in descriptors.
73 HANDLER = 4,
74 INTERCEPTOR = 5,
75 TRANSITION = 6,
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +000076 // Only used as a marker in LookupResult.
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000077 NONEXISTENT = 7
danno@chromium.orgc612e022011-11-10 11:38:15 +000078};
79
80
danno@chromium.orgf005df62013-04-30 16:36:45 +000081class Representation {
82 public:
83 enum Kind {
84 kNone,
machenbach@chromium.org935a7792013-11-12 09:05:18 +000085 kInteger8,
86 kUInteger8,
87 kInteger16,
88 kUInteger16,
danno@chromium.orgf005df62013-04-30 16:36:45 +000089 kSmi,
90 kInteger32,
91 kDouble,
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000092 kHeapObject,
danno@chromium.orgf005df62013-04-30 16:36:45 +000093 kTagged,
94 kExternal,
95 kNumRepresentations
96 };
97
98 Representation() : kind_(kNone) { }
99
100 static Representation None() { return Representation(kNone); }
101 static Representation Tagged() { return Representation(kTagged); }
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000102 static Representation Integer8() { return Representation(kInteger8); }
103 static Representation UInteger8() { return Representation(kUInteger8); }
104 static Representation Integer16() { return Representation(kInteger16); }
105 static Representation UInteger16() {
106 return Representation(kUInteger16);
107 }
danno@chromium.orgf005df62013-04-30 16:36:45 +0000108 static Representation Smi() { return Representation(kSmi); }
109 static Representation Integer32() { return Representation(kInteger32); }
110 static Representation Double() { return Representation(kDouble); }
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000111 static Representation HeapObject() { return Representation(kHeapObject); }
danno@chromium.orgf005df62013-04-30 16:36:45 +0000112 static Representation External() { return Representation(kExternal); }
113
114 static Representation FromKind(Kind kind) { return Representation(kind); }
115
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000116 // TODO(rossberg): this should die eventually.
117 static Representation FromType(TypeInfo info);
118 static Representation FromType(Handle<Type> type);
119
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000120 bool Equals(const Representation& other) const {
danno@chromium.orgf005df62013-04-30 16:36:45 +0000121 return kind_ == other.kind_;
122 }
123
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000124 bool IsCompatibleForLoad(const Representation& other) const {
125 return (IsDouble() && other.IsDouble()) ||
126 (!IsDouble() && !other.IsDouble());
127 }
128
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000129 bool IsCompatibleForStore(const Representation& other) const {
130 return Equals(other);
131 }
132
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000133 bool is_more_general_than(const Representation& other) const {
danno@chromium.orgf005df62013-04-30 16:36:45 +0000134 ASSERT(kind_ != kExternal);
135 ASSERT(other.kind_ != kExternal);
danno@chromium.org1fd77d52013-06-07 16:01:45 +0000136 if (IsHeapObject()) return other.IsDouble() || other.IsNone();
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000137 if (kind_ == kUInteger8 && other.kind_ == kInteger8) return false;
138 if (kind_ == kUInteger16 && other.kind_ == kInteger16) return false;
danno@chromium.orgf005df62013-04-30 16:36:45 +0000139 return kind_ > other.kind_;
140 }
141
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000142 bool fits_into(const Representation& other) const {
143 return other.is_more_general_than(*this) || other.Equals(*this);
144 }
145
danno@chromium.orgf005df62013-04-30 16:36:45 +0000146 Representation generalize(Representation other) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000147 if (other.fits_into(*this)) return *this;
148 if (other.is_more_general_than(*this)) return other;
149 return Representation::Tagged();
danno@chromium.orgf005df62013-04-30 16:36:45 +0000150 }
151
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000152 int size() const {
153 ASSERT(!IsNone());
154 if (IsInteger8() || IsUInteger8()) {
155 return sizeof(uint8_t);
156 }
157 if (IsInteger16() || IsUInteger16()) {
158 return sizeof(uint16_t);
159 }
160 if (IsInteger32()) {
161 return sizeof(uint32_t);
162 }
163 return kPointerSize;
164 }
165
danno@chromium.orgf005df62013-04-30 16:36:45 +0000166 Kind kind() const { return static_cast<Kind>(kind_); }
167 bool IsNone() const { return kind_ == kNone; }
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000168 bool IsInteger8() const { return kind_ == kInteger8; }
169 bool IsUInteger8() const { return kind_ == kUInteger8; }
170 bool IsInteger16() const { return kind_ == kInteger16; }
171 bool IsUInteger16() const { return kind_ == kUInteger16; }
danno@chromium.orgf005df62013-04-30 16:36:45 +0000172 bool IsTagged() const { return kind_ == kTagged; }
173 bool IsSmi() const { return kind_ == kSmi; }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000174 bool IsSmiOrTagged() const { return IsSmi() || IsTagged(); }
danno@chromium.orgf005df62013-04-30 16:36:45 +0000175 bool IsInteger32() const { return kind_ == kInteger32; }
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000176 bool IsSmiOrInteger32() const { return IsSmi() || IsInteger32(); }
danno@chromium.orgf005df62013-04-30 16:36:45 +0000177 bool IsDouble() const { return kind_ == kDouble; }
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000178 bool IsHeapObject() const { return kind_ == kHeapObject; }
danno@chromium.orgf005df62013-04-30 16:36:45 +0000179 bool IsExternal() const { return kind_ == kExternal; }
180 bool IsSpecialization() const {
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000181 return IsInteger8() || IsUInteger8() ||
182 IsInteger16() || IsUInteger16() ||
183 IsSmi() || IsInteger32() || IsDouble();
danno@chromium.orgf005df62013-04-30 16:36:45 +0000184 }
185 const char* Mnemonic() const;
186
187 private:
188 explicit Representation(Kind k) : kind_(k) { }
189
190 // Make sure kind fits in int8.
191 STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte));
192
193 int8_t kind_;
194};
195
196
danno@chromium.orgc612e022011-11-10 11:38:15 +0000197// PropertyDetails captures type and attributes for a property.
198// They are used both in property dictionaries and instance descriptors.
199class PropertyDetails BASE_EMBEDDED {
200 public:
201 PropertyDetails(PropertyAttributes attributes,
202 PropertyType type,
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000203 int index) {
danno@chromium.orgc612e022011-11-10 11:38:15 +0000204 value_ = TypeField::encode(type)
205 | AttributesField::encode(attributes)
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000206 | DictionaryStorageField::encode(index);
danno@chromium.orgc612e022011-11-10 11:38:15 +0000207
208 ASSERT(type == this->type());
209 ASSERT(attributes == this->attributes());
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000210 }
211
212 PropertyDetails(PropertyAttributes attributes,
213 PropertyType type,
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000214 Representation representation,
215 int field_index = 0) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000216 value_ = TypeField::encode(type)
217 | AttributesField::encode(attributes)
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000218 | RepresentationField::encode(EncodeRepresentation(representation))
219 | FieldIndexField::encode(field_index);
danno@chromium.orgc612e022011-11-10 11:38:15 +0000220 }
221
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000222 int pointer() { return DescriptorPointer::decode(value_); }
223
224 PropertyDetails set_pointer(int i) { return PropertyDetails(value_, i); }
225
danno@chromium.orgf005df62013-04-30 16:36:45 +0000226 PropertyDetails CopyWithRepresentation(Representation representation) {
227 return PropertyDetails(value_, representation);
228 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000229 PropertyDetails CopyAddAttributes(PropertyAttributes new_attributes) {
230 new_attributes =
231 static_cast<PropertyAttributes>(attributes() | new_attributes);
232 return PropertyDetails(value_, new_attributes);
233 }
danno@chromium.orgf005df62013-04-30 16:36:45 +0000234
danno@chromium.orgc612e022011-11-10 11:38:15 +0000235 // Conversion for storing details as Object*.
236 explicit inline PropertyDetails(Smi* smi);
237 inline Smi* AsSmi();
238
danno@chromium.orgf005df62013-04-30 16:36:45 +0000239 static uint8_t EncodeRepresentation(Representation representation) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000240 return representation.kind();
danno@chromium.orgf005df62013-04-30 16:36:45 +0000241 }
242
243 static Representation DecodeRepresentation(uint32_t bits) {
danno@chromium.orgf005df62013-04-30 16:36:45 +0000244 return Representation::FromKind(static_cast<Representation::Kind>(bits));
245 }
246
danno@chromium.orgc612e022011-11-10 11:38:15 +0000247 PropertyType type() { return TypeField::decode(value_); }
248
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +0000249 PropertyAttributes attributes() const {
250 return AttributesField::decode(value_);
251 }
danno@chromium.orgc612e022011-11-10 11:38:15 +0000252
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000253 int dictionary_index() {
254 return DictionaryStorageField::decode(value_);
255 }
256
danno@chromium.orgf005df62013-04-30 16:36:45 +0000257 Representation representation() {
danno@chromium.org1fd77d52013-06-07 16:01:45 +0000258 ASSERT(type() != NORMAL);
danno@chromium.orgf005df62013-04-30 16:36:45 +0000259 return DecodeRepresentation(RepresentationField::decode(value_));
260 }
261
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000262 int field_index() {
263 return FieldIndexField::decode(value_);
264 }
265
danno@chromium.orgc612e022011-11-10 11:38:15 +0000266 inline PropertyDetails AsDeleted();
267
268 static bool IsValidIndex(int index) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000269 return DictionaryStorageField::is_valid(index);
danno@chromium.orgc612e022011-11-10 11:38:15 +0000270 }
271
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +0000272 bool IsReadOnly() const { return (attributes() & READ_ONLY) != 0; }
273 bool IsDontDelete() const { return (attributes() & DONT_DELETE) != 0; }
274 bool IsDontEnum() const { return (attributes() & DONT_ENUM) != 0; }
275 bool IsDeleted() const { return DeletedField::decode(value_) != 0;}
danno@chromium.orgc612e022011-11-10 11:38:15 +0000276
277 // Bit fields in value_ (type, shift, size). Must be public so the
278 // constants can be embedded in generated code.
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000279 class TypeField: public BitField<PropertyType, 0, 3> {};
280 class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000281
282 // Bit fields for normalized objects.
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000283 class DeletedField: public BitField<uint32_t, 6, 1> {};
284 class DictionaryStorageField: public BitField<uint32_t, 7, 24> {};
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000285
286 // Bit fields for fast objects.
287 class DescriptorPointer: public BitField<uint32_t, 6, 11> {};
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000288 class RepresentationField: public BitField<uint32_t, 17, 4> {};
289 class FieldIndexField: public BitField<uint32_t, 21, 10> {};
danno@chromium.orgc612e022011-11-10 11:38:15 +0000290
291 static const int kInitialIndex = 1;
292
293 private:
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000294 PropertyDetails(int value, int pointer) {
danno@chromium.orgf005df62013-04-30 16:36:45 +0000295 value_ = DescriptorPointer::update(value, pointer);
296 }
297 PropertyDetails(int value, Representation representation) {
298 value_ = RepresentationField::update(
299 value, EncodeRepresentation(representation));
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000300 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000301 PropertyDetails(int value, PropertyAttributes attributes) {
302 value_ = AttributesField::update(value, attributes);
303 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000304
danno@chromium.orgc612e022011-11-10 11:38:15 +0000305 uint32_t value_;
306};
307
308} } // namespace v8::internal
309
310#endif // V8_PROPERTY_DETAILS_H_