Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Side by Side Diff: src/objects.cc

Issue 12297012: Runtime version of declarative native accessors. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 String* name, 156 String* name,
157 PropertyAttributes* attributes) { 157 PropertyAttributes* attributes) {
158 LookupResult result(name->GetIsolate()); 158 LookupResult result(name->GetIsolate());
159 Lookup(name, &result); 159 Lookup(name, &result);
160 MaybeObject* value = GetProperty(receiver, &result, name, attributes); 160 MaybeObject* value = GetProperty(receiver, &result, name, attributes);
161 ASSERT(*attributes <= ABSENT); 161 ASSERT(*attributes <= ABSENT);
162 return value; 162 return value;
163 } 163 }
164 164
165 165
166 template<typename To>
167 static inline To* CheckedCast(void *from) {
168 uintptr_t temp = reinterpret_cast<uintptr_t>(from);
169 ASSERT(temp % sizeof(To) == 0);
170 return reinterpret_cast<To*>(temp);
171 }
172
173
174 static MaybeObject* PerformCompare(const BitmaskCompareDescriptor& descriptor,
175 char* ptr,
176 Isolate* isolate) {
177 uint32_t bitmask = descriptor.bitmask;
178 uint32_t compare_value = descriptor.compare_value;
179 uint32_t value;
180 switch (descriptor.size) {
181 case 1:
182 value = static_cast<uint32_t>(*CheckedCast<uint8_t>(ptr));
183 compare_value &= 0xff;
184 bitmask &= 0xff;
185 break;
186 case 2:
187 value = static_cast<uint32_t>(*CheckedCast<uint16_t>(ptr));
188 compare_value &= 0xffff;
189 bitmask &= 0xffff;
190 break;
191 case 4:
192 value = *CheckedCast<uint32_t>(ptr);
193 break;
194 default:
195 UNREACHABLE();
196 return NULL;
197 }
198 bool result = (bitmask & value) == (bitmask & compare_value);
199 return result ? isolate->heap()->true_value()
200 : isolate->heap()->false_value();
201 }
202
203
204 static MaybeObject* PerformCompare(const PointerCompareDescriptor& descriptor,
205 char* ptr,
206 Isolate* isolate) {
207 uintptr_t compare_value =
208 reinterpret_cast<uintptr_t>(descriptor.compare_value);
209 uintptr_t value = *CheckedCast<uintptr_t>(ptr);
210 bool result = compare_value == value;
211 return result ? isolate->heap()->true_value()
212 : isolate->heap()->false_value();
213 }
214
215
216 static MaybeObject* GetPrimitiveValue(
217 const PrimitiveValueDescriptor& descriptor,
218 char* ptr,
219 Isolate* isolate) {
220 int32_t int32_value;
221 switch (descriptor.data_type) {
222 case kDescriptorInt8Type:
223 int32_value = *CheckedCast<int8_t>(ptr);
224 break;
225 case kDescriptorUint8Type:
226 int32_value = *CheckedCast<uint8_t>(ptr);
227 break;
228 case kDescriptorInt16Type:
229 int32_value = *CheckedCast<int16_t>(ptr);
230 break;
231 case kDescriptorUint16Type:
232 int32_value = *CheckedCast<uint16_t>(ptr);
233 break;
234 case kDescriptorInt32Type:
235 int32_value = *CheckedCast<int32_t>(ptr);
236 break;
237 case kDescriptorUint32Type: {
238 uint32_t value = *CheckedCast<uint32_t>(ptr);
239 return *isolate->factory()->NewNumberFromUint(value);
Sven Panne 2013/02/19 08:41:16 Using Handles in non-handlified code is not GC saf
240 }
241 case kDescriptorBoolType: {
242 uint8_t byte = *CheckedCast<uint8_t>(ptr);
243 bool result = byte & (0x1 << descriptor.bool_offset);
244 return result ? isolate->heap()->true_value()
245 : isolate->heap()->false_value();
246 }
247 case kDescriptorFloatType: {
248 float value = *CheckedCast<float>(ptr);
249 return *isolate->factory()->NewNumber(value);
Sven Panne 2013/02/19 08:41:16 Same here...
250 }
251 case kDescriptorDoubleType: {
252 double value = *CheckedCast<double>(ptr);
253 return *isolate->factory()->NewNumber(value);
Sven Panne 2013/02/19 08:41:16 Same here...
254 }
255 default:
256 UNREACHABLE();
257 return NULL;
258 }
259 return *isolate->factory()->NewNumberFromInt(int32_value);
Sven Panne 2013/02/19 08:41:16 Same here...
260 }
261
262
263 static MaybeObject* GetDeclaredAccessorProperty(Object* receiver,
264 DeclaredAccessorInfo* info,
265 Isolate* isolate) {
266 v8::AccessorDescriptor descriptor;
267 // Simulate a handle.
268 char* current = NULL; // This will be set in the first loop iteration.
269 // Dereference through the chain.
270 {
271 AssertNoAllocation no_allocation;
272 ByteArray* byte_array = info->descriptor()->serialized_descriptor();
273 int length = byte_array->length();
274 uint8_t* bytes = byte_array->GetDataStartAddress();
275 AccessorDescriptorDeserializer deserializer(length, bytes);
276 bool current_is_object = true;
277 bool first = true;
278 bool complete;
279 do {
280 ASSERT(!deserializer.Complete());
281 deserializer.Next(&descriptor);
282 if (!current_is_object) {
283 // Dereference pointer.
284 current = *reinterpret_cast<char**>(current);
285 } else {
286 // Open handle and get internal field value.
287 Object* object;
288 if (first) {
289 object = receiver;
290 first = false;
291 } else {
292 current = *reinterpret_cast<char**>(current);
293 object = *CheckedCast<Object*>(current);
294 }
295 Object* smi = JSObject::cast(object)->GetInternalField(descriptor.intern al_field);
296 ASSERT(smi->IsSmi());
297 current = reinterpret_cast<char*>(smi);
298 }
299 current += descriptor.byte_offset;
300 complete = deserializer.Complete();
301 switch (descriptor.type) {
302 case kDescriptorPointerDereference:
303 if (complete) {
304 return *CheckedCast<Object*>(current);
305 }
306 current_is_object = false;
307 break;
308 case kDescriptorInternalFieldDereference:
309 if (complete) {
310 return *CheckedCast<Object*>(current);
311 }
312 current_is_object = true;
313 break;
314 default:
Sven Panne 2013/02/19 08:41:16 No default cases, explicitly handle all cases.
315 ASSERT(complete);
316 break;
317 }
318 } while (!complete);
319 }
320 // Can now process instructions requiring allocation.
321 switch (descriptor.type) {
322 case kDescriptorBitmaskCompare:
323 return PerformCompare(descriptor.bitmask_compare_descriptor,
324 current,
325 isolate);
326 case kDescriptorPointerCompare:
327 return PerformCompare(descriptor.pointer_compare_descriptor,
328 current,
329 isolate);
330 case kDescriptorPrimitiveValue:
331 return GetPrimitiveValue(descriptor.primitive_value_descriptor,
332 current,
333 isolate);
334 default:
Sven Panne 2013/02/19 08:41:16 No default cases, explicitly handle all cases.
335 break;
336 }
337 UNREACHABLE();
338 return NULL;
339 }
340
341
166 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver, 342 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver,
167 Object* structure, 343 Object* structure,
168 String* name) { 344 String* name) {
169 Isolate* isolate = name->GetIsolate(); 345 Isolate* isolate = name->GetIsolate();
170 // To accommodate both the old and the new api we switch on the 346 // To accommodate both the old and the new api we switch on the
171 // data structure used to store the callbacks. Eventually foreign 347 // data structure used to store the callbacks. Eventually foreign
172 // callbacks should be phased out. 348 // callbacks should be phased out.
173 if (structure->IsForeign()) { 349 if (structure->IsForeign()) {
174 AccessorDescriptor* callback = 350 AccessorDescriptor* callback =
175 reinterpret_cast<AccessorDescriptor*>( 351 reinterpret_cast<AccessorDescriptor*>(
176 Foreign::cast(structure)->foreign_address()); 352 Foreign::cast(structure)->foreign_address());
177 MaybeObject* value = (callback->getter)(receiver, callback->data); 353 MaybeObject* value = (callback->getter)(receiver, callback->data);
178 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 354 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
179 return value; 355 return value;
180 } 356 }
181 357
182 // api style callbacks. 358 // api style callbacks.
183 if (structure->IsExecutableAccessorInfo()) { 359 if (structure->IsAccessorInfo()) {
184 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure); 360 if (!AccessorInfo::cast(structure)->IsCompatibleReceiver(receiver)) {
185 if (!data->IsCompatibleReceiver(receiver)) {
186 Handle<Object> name_handle(name); 361 Handle<Object> name_handle(name);
187 Handle<Object> receiver_handle(receiver); 362 Handle<Object> receiver_handle(receiver);
188 Handle<Object> args[2] = { name_handle, receiver_handle }; 363 Handle<Object> args[2] = { name_handle, receiver_handle };
189 Handle<Object> error = 364 Handle<Object> error =
190 isolate->factory()->NewTypeError("incompatible_method_receiver", 365 isolate->factory()->NewTypeError("incompatible_method_receiver",
191 HandleVector(args, 366 HandleVector(args,
192 ARRAY_SIZE(args))); 367 ARRAY_SIZE(args)));
193 return isolate->Throw(*error); 368 return isolate->Throw(*error);
194 } 369 }
370 if (structure->IsDeclaredAccessorInfo()) {
371 return GetDeclaredAccessorProperty(receiver,
372 DeclaredAccessorInfo::cast(structure),
373 isolate);
374 }
375 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure);
195 Object* fun_obj = data->getter(); 376 Object* fun_obj = data->getter();
196 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); 377 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
197 if (call_fun == NULL) return isolate->heap()->undefined_value(); 378 if (call_fun == NULL) return isolate->heap()->undefined_value();
198 HandleScope scope(isolate); 379 HandleScope scope(isolate);
199 JSObject* self = JSObject::cast(receiver); 380 JSObject* self = JSObject::cast(receiver);
200 Handle<String> key(name); 381 Handle<String> key(name);
201 LOG(isolate, ApiNamedPropertyAccess("load", self, name)); 382 LOG(isolate, ApiNamedPropertyAccess("load", self, name));
202 CustomArguments args(isolate, data->data(), self, this); 383 CustomArguments args(isolate, data->data(), self, this);
203 v8::AccessorInfo info(args.end()); 384 v8::AccessorInfo info(args.end());
204 v8::Handle<v8::Value> result; 385 v8::Handle<v8::Value> result;
(...skipping 15 matching lines...) Expand all
220 if (structure->IsAccessorPair()) { 401 if (structure->IsAccessorPair()) {
221 Object* getter = AccessorPair::cast(structure)->getter(); 402 Object* getter = AccessorPair::cast(structure)->getter();
222 if (getter->IsSpecFunction()) { 403 if (getter->IsSpecFunction()) {
223 // TODO(rossberg): nicer would be to cast to some JSCallable here... 404 // TODO(rossberg): nicer would be to cast to some JSCallable here...
224 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter)); 405 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
225 } 406 }
226 // Getter is not a function. 407 // Getter is not a function.
227 return isolate->heap()->undefined_value(); 408 return isolate->heap()->undefined_value();
228 } 409 }
229 410
230 // TODO(dcarney): Handle correctly.
231 if (structure->IsDeclaredAccessorInfo()) {
232 return isolate->heap()->undefined_value();
233 }
234
235 UNREACHABLE(); 411 UNREACHABLE();
236 return NULL; 412 return NULL;
237 } 413 }
238 414
239 415
240 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw, 416 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
241 String* name_raw) { 417 String* name_raw) {
242 Isolate* isolate = GetIsolate(); 418 Isolate* isolate = GetIsolate();
243 HandleScope scope(isolate); 419 HandleScope scope(isolate);
244 Handle<Object> receiver(receiver_raw); 420 Handle<Object> receiver(receiver_raw);
(...skipping 9531 matching lines...) Expand 10 before | Expand all | Expand 10 after
9776 Object* getter = AccessorPair::cast(structure)->getter(); 9952 Object* getter = AccessorPair::cast(structure)->getter();
9777 if (getter->IsSpecFunction()) { 9953 if (getter->IsSpecFunction()) {
9778 // TODO(rossberg): nicer would be to cast to some JSCallable here... 9954 // TODO(rossberg): nicer would be to cast to some JSCallable here...
9779 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter)); 9955 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
9780 } 9956 }
9781 // Getter is not a function. 9957 // Getter is not a function.
9782 return isolate->heap()->undefined_value(); 9958 return isolate->heap()->undefined_value();
9783 } 9959 }
9784 9960
9785 if (structure->IsDeclaredAccessorInfo()) { 9961 if (structure->IsDeclaredAccessorInfo()) {
9786 // TODO(dcarney): Handle correctly. 9962 return GetDeclaredAccessorProperty(receiver,
9787 return isolate->heap()->undefined_value(); 9963 DeclaredAccessorInfo::cast(structure),
9964 isolate);
9788 } 9965 }
9789 9966
9790 UNREACHABLE(); 9967 UNREACHABLE();
9791 return NULL; 9968 return NULL;
9792 } 9969 }
9793 9970
9794 9971
9795 MaybeObject* JSObject::SetElementWithCallback(Object* structure, 9972 MaybeObject* JSObject::SetElementWithCallback(Object* structure,
9796 uint32_t index, 9973 uint32_t index,
9797 Object* value, 9974 Object* value,
(...skipping 3742 matching lines...) Expand 10 before | Expand all | Expand 10 after
13540 } 13717 }
13541 13718
13542 13719
13543 void ObjectHashTable::RemoveEntry(int entry) { 13720 void ObjectHashTable::RemoveEntry(int entry) {
13544 set_the_hole(EntryToIndex(entry)); 13721 set_the_hole(EntryToIndex(entry));
13545 set_the_hole(EntryToIndex(entry) + 1); 13722 set_the_hole(EntryToIndex(entry) + 1);
13546 ElementRemoved(); 13723 ElementRemoved();
13547 } 13724 }
13548 13725
13549 13726
13727 class AccessorDescriptorLengthCounter {
Sven Panne 2013/02/19 08:41:16 Very unclear what this does and why it is needed..
13728 public:
13729 AccessorDescriptorLengthCounter() : length_(0), error_(false), depth_(0) {}
13730
13731 template<typename T>
13732 bool ShouldVisit(T* descriptor) {
13733 return !error_ && descriptor != NULL;
13734 }
13735
13736 bool ShouldVisit(v8::AccessorDescriptor* descriptor) {
13737 if (descriptor == NULL) return false;
13738 // TODO(dcarney): Move this limit to v8.h
13739 if (depth_ > 5) error_ = true;
13740 depth_++;
13741 return !error_;
13742 }
13743
13744 bool ShouldVisit(v8::PrimitiveValueDescriptor* descriptor) {
13745 ASSERT(descriptor != NULL);
13746 if (descriptor->data_type == kDescriptorInt8Type &&
13747 descriptor->bool_offset >= 8) {
13748 error_ = true;
13749 }
13750 return !error_;
13751 }
13752
13753 bool ShouldVisit(v8::BitmaskCompareDescriptor* descriptor) {
13754 ASSERT(descriptor != NULL);
13755 switch (descriptor->size) {
13756 case 1:
13757 case 2:
13758 case 4:
13759 break;
13760 default:
13761 error_ = true;
13762 break;
13763 }
13764 return !error_;
13765 }
13766
13767 template<typename T>
13768 void Visit(T* member) {
13769 length_ += AccessorDescriptorSerialization<T>::kArraySize;
13770 }
13771
13772 void VisitError() { error_ = true; }
13773
13774 uint16_t Length() { return error_ ? -1 : length_; }
13775
13776 private:
13777 uint16_t length_;
13778 bool error_;
13779 uint8_t depth_;
13780 DISALLOW_COPY_AND_ASSIGN(AccessorDescriptorLengthCounter);
13781 };
13782
13783
13784 class AccessorDescriptorSerializer : public AccessorDescriptorSerializerBase {
13785 public:
13786 AccessorDescriptorSerializer(uint16_t length, uint8_t* storage) :
13787 AccessorDescriptorSerializerBase(length, storage) {
13788 }
13789
13790 template<typename T>
13791 bool ShouldVisit(T* descriptor) {
13792 return descriptor != NULL;
13793 }
13794
13795 template<typename T>
13796 void Visit(T* member) {
13797 typedef AccessorDescriptorSerialization<T> Ser;
13798 CHECK(offset_ + Ser::kArraySize <= length_);
13799 Ser::Serialize(*member, &storage_[offset_]);
13800 offset_ += Ser::kArraySize;
13801 }
13802
13803 private:
13804 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorDescriptorSerializer);
13805 };
13806
13807
13808 int DeclaredAccessorDescriptor::SerializedLength(
13809 const v8::AccessorDescriptor* descriptor) {
13810 AccessorDescriptorLengthCounter length_counter;
13811 v8::DescriptorVisitorHelper::VisitDescriptor(
13812 const_cast<v8::AccessorDescriptor*>(descriptor), &length_counter);
13813 return length_counter.Length();
13814 }
13815
13816
13817 Handle<DeclaredAccessorDescriptor> DeclaredAccessorDescriptor::Create(
13818 const v8::AccessorDescriptor* descriptor,
13819 Isolate* isolate) {
13820 int length = SerializedLength(descriptor);
13821 if (length <= 0) return Handle<DeclaredAccessorDescriptor>();
13822 Handle<ByteArray> data = isolate->factory()->NewByteArray(length);
13823 {
13824 AssertNoAllocation no_allocation;
13825 uint8_t* storage = data->GetDataStartAddress();
13826 AccessorDescriptorSerializer serializer(length, storage);
13827 v8::DescriptorVisitorHelper::VisitDescriptor(
13828 const_cast<v8::AccessorDescriptor*>(descriptor), &serializer);
13829 CHECK(serializer.Complete());
13830 }
13831 Handle<DeclaredAccessorDescriptor> value =
13832 isolate->factory()->NewDeclaredAccessorDescriptor();
13833 value->set_serialized_descriptor(*data);
13834 // TODO(dcarney): Insert into global hash set.
13835 return value;
13836 }
13837
13838
13550 #ifdef ENABLE_DEBUGGER_SUPPORT 13839 #ifdef ENABLE_DEBUGGER_SUPPORT
13551 // Check if there is a break point at this code position. 13840 // Check if there is a break point at this code position.
13552 bool DebugInfo::HasBreakPoint(int code_position) { 13841 bool DebugInfo::HasBreakPoint(int code_position) {
13553 // Get the break point info object for this code position. 13842 // Get the break point info object for this code position.
13554 Object* break_point_info = GetBreakPointInfo(code_position); 13843 Object* break_point_info = GetBreakPointInfo(code_position);
13555 13844
13556 // If there is no break point info object or no break points in the break 13845 // If there is no break point info object or no break points in the break
13557 // point info object there is no break point at this code position. 13846 // point info object there is no break point at this code position.
13558 if (break_point_info->IsUndefined()) return false; 13847 if (break_point_info->IsUndefined()) return false;
13559 return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0; 13848 return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
13923 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 14212 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13924 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 14213 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13925 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 14214 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13926 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 14215 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13927 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 14216 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13928 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 14217 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13929 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 14218 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13930 } 14219 }
13931 14220
13932 } } // namespace v8::internal 14221 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698