1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
10 #include "deoptimizer.h"
11 #include "execution.h"
13 #include "frames-inl.h"
16 #include "property-details.h"
23 Handle<AccessorInfo> Accessors::MakeAccessor(
26 AccessorGetterCallback getter,
27 AccessorSetterCallback setter,
28 PropertyAttributes attributes) {
29 Factory* factory = isolate->factory();
30 Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
31 info->set_property_attributes(attributes);
32 info->set_all_can_read(false);
33 info->set_all_can_write(false);
34 info->set_prohibits_overwriting(false);
35 info->set_name(*name);
36 Handle<Object> get = v8::FromCData(isolate, getter);
37 Handle<Object> set = v8::FromCData(isolate, setter);
38 info->set_getter(*get);
39 info->set_setter(*set);
45 static C* FindInstanceOf(Isolate* isolate, Object* obj) {
46 for (Object* cur = obj; !cur->IsNull(); cur = cur->GetPrototype(isolate)) {
47 if (Is<C>(cur)) return C::cast(cur);
53 static V8_INLINE bool CheckForName(Handle<String> name,
54 Handle<String> property_name,
57 if (String::Equals(name, property_name)) {
58 *object_offset = offset;
65 // Returns true for properties that are accessors to object fields.
66 // If true, *object_offset contains offset of object field.
68 bool Accessors::IsJSObjectFieldAccessor(typename T::TypeHandle type,
71 Isolate* isolate = name->GetIsolate();
73 if (type->Is(T::String())) {
74 return CheckForName(name, isolate->factory()->length_string(),
75 String::kLengthOffset, object_offset);
78 if (!type->IsClass()) return false;
79 Handle<Map> map = type->AsClass()->Map();
81 switch (map->instance_type()) {
84 CheckForName(name, isolate->factory()->length_string(),
85 JSArray::kLengthOffset, object_offset);
86 case JS_TYPED_ARRAY_TYPE:
88 CheckForName(name, isolate->factory()->length_string(),
89 JSTypedArray::kLengthOffset, object_offset) ||
90 CheckForName(name, isolate->factory()->byte_length_string(),
91 JSTypedArray::kByteLengthOffset, object_offset) ||
92 CheckForName(name, isolate->factory()->byte_offset_string(),
93 JSTypedArray::kByteOffsetOffset, object_offset);
94 case JS_ARRAY_BUFFER_TYPE:
96 CheckForName(name, isolate->factory()->byte_length_string(),
97 JSArrayBuffer::kByteLengthOffset, object_offset);
98 case JS_DATA_VIEW_TYPE:
100 CheckForName(name, isolate->factory()->byte_length_string(),
101 JSDataView::kByteLengthOffset, object_offset) ||
102 CheckForName(name, isolate->factory()->byte_offset_string(),
103 JSDataView::kByteOffsetOffset, object_offset);
111 bool Accessors::IsJSObjectFieldAccessor<Type>(Type* type,
117 bool Accessors::IsJSObjectFieldAccessor<HeapType>(Handle<HeapType> type,
123 // Accessors::ArrayLength
127 // The helper function will 'flatten' Number objects.
128 Handle<Object> Accessors::FlattenNumber(Isolate* isolate,
129 Handle<Object> value) {
130 if (value->IsNumber() || !value->IsJSValue()) return value;
131 Handle<JSValue> wrapper = Handle<JSValue>::cast(value);
132 ASSERT(wrapper->GetIsolate()->context()->native_context()->number_function()->
134 if (wrapper->map() ==
135 isolate->context()->native_context()->number_function()->initial_map()) {
136 return handle(wrapper->value(), isolate);
143 void Accessors::ArrayLengthGetter(
144 v8::Local<v8::String> name,
145 const v8::PropertyCallbackInfo<v8::Value>& info) {
146 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
147 DisallowHeapAllocation no_allocation;
148 HandleScope scope(isolate);
149 Object* object = *Utils::OpenHandle(*info.This());
150 // Traverse the prototype chain until we reach an array.
151 JSArray* holder = FindInstanceOf<JSArray>(isolate, object);
153 if (holder != NULL) {
154 result = holder->length();
156 result = Smi::FromInt(0);
158 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
162 void Accessors::ArrayLengthSetter(
163 v8::Local<v8::String> name,
164 v8::Local<v8::Value> val,
165 const v8::PropertyCallbackInfo<void>& info) {
166 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
167 HandleScope scope(isolate);
168 Handle<JSObject> object = Handle<JSObject>::cast(
169 Utils::OpenHandle(*info.This()));
170 Handle<Object> value = Utils::OpenHandle(*val);
171 // This means one of the object's prototypes is a JSArray and the
172 // object does not have a 'length' property. Calling SetProperty
173 // causes an infinite loop.
174 if (!object->IsJSArray()) {
175 MaybeHandle<Object> maybe_result =
176 JSObject::SetLocalPropertyIgnoreAttributes(
177 object, isolate->factory()->length_string(), value, NONE);
178 maybe_result.Check();
182 value = FlattenNumber(isolate, value);
184 Handle<JSArray> array_handle = Handle<JSArray>::cast(object);
185 MaybeHandle<Object> maybe;
186 Handle<Object> uint32_v;
187 maybe = Execution::ToUint32(isolate, value);
188 if (!maybe.ToHandle(&uint32_v)) {
189 isolate->OptionalRescheduleException(false);
192 Handle<Object> number_v;
193 maybe = Execution::ToNumber(isolate, value);
194 if (!maybe.ToHandle(&number_v)) {
195 isolate->OptionalRescheduleException(false);
199 if (uint32_v->Number() == number_v->Number()) {
200 maybe = JSArray::SetElementsLength(array_handle, uint32_v);
205 isolate->ScheduleThrow(
206 *isolate->factory()->NewRangeError("invalid_array_length",
207 HandleVector<Object>(NULL, 0)));
211 Handle<AccessorInfo> Accessors::ArrayLengthInfo(
212 Isolate* isolate, PropertyAttributes attributes) {
213 return MakeAccessor(isolate,
214 isolate->factory()->length_string(),
223 // Accessors::StringLength
226 void Accessors::StringLengthGetter(
227 v8::Local<v8::String> name,
228 const v8::PropertyCallbackInfo<v8::Value>& info) {
229 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
230 DisallowHeapAllocation no_allocation;
231 HandleScope scope(isolate);
232 Object* value = *Utils::OpenHandle(*info.This());
234 if (value->IsJSValue()) value = JSValue::cast(value)->value();
235 if (value->IsString()) {
236 result = Smi::FromInt(String::cast(value)->length());
238 // If object is not a string we return 0 to be compatible with WebKit.
239 // Note: Firefox returns the length of ToString(object).
240 result = Smi::FromInt(0);
242 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
246 void Accessors::StringLengthSetter(
247 v8::Local<v8::String> name,
248 v8::Local<v8::Value> value,
249 const v8::PropertyCallbackInfo<void>& info) {
254 Handle<AccessorInfo> Accessors::StringLengthInfo(
255 Isolate* isolate, PropertyAttributes attributes) {
256 return MakeAccessor(isolate,
257 isolate->factory()->length_string(),
265 // Accessors::ScriptColumnOffset
269 void Accessors::ScriptColumnOffsetGetter(
270 v8::Local<v8::String> name,
271 const v8::PropertyCallbackInfo<v8::Value>& info) {
272 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
273 DisallowHeapAllocation no_allocation;
274 HandleScope scope(isolate);
275 Object* object = *Utils::OpenHandle(*info.This());
276 Object* res = Script::cast(JSValue::cast(object)->value())->column_offset();
277 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
281 void Accessors::ScriptColumnOffsetSetter(
282 v8::Local<v8::String> name,
283 v8::Local<v8::Value> value,
284 const v8::PropertyCallbackInfo<void>& info) {
289 Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
290 Isolate* isolate, PropertyAttributes attributes) {
291 Handle<String> name(isolate->factory()->InternalizeOneByteString(
292 STATIC_ASCII_VECTOR("column_offset")));
293 return MakeAccessor(isolate,
295 &ScriptColumnOffsetGetter,
296 &ScriptColumnOffsetSetter,
302 // Accessors::ScriptId
306 void Accessors::ScriptIdGetter(
307 v8::Local<v8::String> name,
308 const v8::PropertyCallbackInfo<v8::Value>& info) {
309 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
310 DisallowHeapAllocation no_allocation;
311 HandleScope scope(isolate);
312 Object* object = *Utils::OpenHandle(*info.This());
313 Object* id = Script::cast(JSValue::cast(object)->value())->id();
314 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate)));
318 void Accessors::ScriptIdSetter(
319 v8::Local<v8::String> name,
320 v8::Local<v8::Value> value,
321 const v8::PropertyCallbackInfo<void>& info) {
326 Handle<AccessorInfo> Accessors::ScriptIdInfo(
327 Isolate* isolate, PropertyAttributes attributes) {
328 Handle<String> name(isolate->factory()->InternalizeOneByteString(
329 STATIC_ASCII_VECTOR("id")));
330 return MakeAccessor(isolate,
339 // Accessors::ScriptName
343 void Accessors::ScriptNameGetter(
344 v8::Local<v8::String> name,
345 const v8::PropertyCallbackInfo<v8::Value>& info) {
346 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
347 DisallowHeapAllocation no_allocation;
348 HandleScope scope(isolate);
349 Object* object = *Utils::OpenHandle(*info.This());
350 Object* source = Script::cast(JSValue::cast(object)->value())->name();
351 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
355 void Accessors::ScriptNameSetter(
356 v8::Local<v8::String> name,
357 v8::Local<v8::Value> value,
358 const v8::PropertyCallbackInfo<void>& info) {
363 Handle<AccessorInfo> Accessors::ScriptNameInfo(
364 Isolate* isolate, PropertyAttributes attributes) {
365 return MakeAccessor(isolate,
366 isolate->factory()->name_string(),
374 // Accessors::ScriptSource
378 void Accessors::ScriptSourceGetter(
379 v8::Local<v8::String> name,
380 const v8::PropertyCallbackInfo<v8::Value>& info) {
381 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
382 DisallowHeapAllocation no_allocation;
383 HandleScope scope(isolate);
384 Object* object = *Utils::OpenHandle(*info.This());
385 Object* source = Script::cast(JSValue::cast(object)->value())->source();
386 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
390 void Accessors::ScriptSourceSetter(
391 v8::Local<v8::String> name,
392 v8::Local<v8::Value> value,
393 const v8::PropertyCallbackInfo<void>& info) {
398 Handle<AccessorInfo> Accessors::ScriptSourceInfo(
399 Isolate* isolate, PropertyAttributes attributes) {
400 return MakeAccessor(isolate,
401 isolate->factory()->source_string(),
409 // Accessors::ScriptLineOffset
413 void Accessors::ScriptLineOffsetGetter(
414 v8::Local<v8::String> name,
415 const v8::PropertyCallbackInfo<v8::Value>& info) {
416 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
417 DisallowHeapAllocation no_allocation;
418 HandleScope scope(isolate);
419 Object* object = *Utils::OpenHandle(*info.This());
420 Object* res = Script::cast(JSValue::cast(object)->value())->line_offset();
421 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
425 void Accessors::ScriptLineOffsetSetter(
426 v8::Local<v8::String> name,
427 v8::Local<v8::Value> value,
428 const v8::PropertyCallbackInfo<void>& info) {
433 Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
434 Isolate* isolate, PropertyAttributes attributes) {
435 Handle<String> name(isolate->factory()->InternalizeOneByteString(
436 STATIC_ASCII_VECTOR("line_offset")));
437 return MakeAccessor(isolate,
439 &ScriptLineOffsetGetter,
440 &ScriptLineOffsetSetter,
446 // Accessors::ScriptType
450 void Accessors::ScriptTypeGetter(
451 v8::Local<v8::String> name,
452 const v8::PropertyCallbackInfo<v8::Value>& info) {
453 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
454 DisallowHeapAllocation no_allocation;
455 HandleScope scope(isolate);
456 Object* object = *Utils::OpenHandle(*info.This());
457 Object* res = Script::cast(JSValue::cast(object)->value())->type();
458 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
462 void Accessors::ScriptTypeSetter(
463 v8::Local<v8::String> name,
464 v8::Local<v8::Value> value,
465 const v8::PropertyCallbackInfo<void>& info) {
470 Handle<AccessorInfo> Accessors::ScriptTypeInfo(
471 Isolate* isolate, PropertyAttributes attributes) {
472 Handle<String> name(isolate->factory()->InternalizeOneByteString(
473 STATIC_ASCII_VECTOR("type")));
474 return MakeAccessor(isolate,
483 // Accessors::ScriptCompilationType
487 void Accessors::ScriptCompilationTypeGetter(
488 v8::Local<v8::String> name,
489 const v8::PropertyCallbackInfo<v8::Value>& info) {
490 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
491 DisallowHeapAllocation no_allocation;
492 HandleScope scope(isolate);
493 Object* object = *Utils::OpenHandle(*info.This());
494 Object* res = Smi::FromInt(
495 Script::cast(JSValue::cast(object)->value())->compilation_type());
496 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
500 void Accessors::ScriptCompilationTypeSetter(
501 v8::Local<v8::String> name,
502 v8::Local<v8::Value> value,
503 const v8::PropertyCallbackInfo<void>& info) {
508 Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
509 Isolate* isolate, PropertyAttributes attributes) {
510 Handle<String> name(isolate->factory()->InternalizeOneByteString(
511 STATIC_ASCII_VECTOR("compilation_type")));
512 return MakeAccessor(isolate,
514 &ScriptCompilationTypeGetter,
515 &ScriptCompilationTypeSetter,
521 // Accessors::ScriptGetLineEnds
525 void Accessors::ScriptLineEndsGetter(
526 v8::Local<v8::String> name,
527 const v8::PropertyCallbackInfo<v8::Value>& info) {
528 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
529 HandleScope scope(isolate);
530 Handle<Object> object = Utils::OpenHandle(*info.This());
531 Handle<Script> script(
532 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
533 Script::InitLineEnds(script);
534 ASSERT(script->line_ends()->IsFixedArray());
535 Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
536 // We do not want anyone to modify this array from JS.
537 ASSERT(*line_ends == isolate->heap()->empty_fixed_array() ||
538 line_ends->map() == isolate->heap()->fixed_cow_array_map());
539 Handle<JSArray> js_array =
540 isolate->factory()->NewJSArrayWithElements(line_ends);
541 info.GetReturnValue().Set(Utils::ToLocal(js_array));
545 void Accessors::ScriptLineEndsSetter(
546 v8::Local<v8::String> name,
547 v8::Local<v8::Value> value,
548 const v8::PropertyCallbackInfo<void>& info) {
553 Handle<AccessorInfo> Accessors::ScriptLineEndsInfo(
554 Isolate* isolate, PropertyAttributes attributes) {
555 Handle<String> name(isolate->factory()->InternalizeOneByteString(
556 STATIC_ASCII_VECTOR("line_ends")));
557 return MakeAccessor(isolate,
559 &ScriptLineEndsGetter,
560 &ScriptLineEndsSetter,
566 // Accessors::ScriptGetContextData
570 void Accessors::ScriptContextDataGetter(
571 v8::Local<v8::String> name,
572 const v8::PropertyCallbackInfo<v8::Value>& info) {
573 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
574 DisallowHeapAllocation no_allocation;
575 HandleScope scope(isolate);
576 Object* object = *Utils::OpenHandle(*info.This());
577 Object* res = Script::cast(JSValue::cast(object)->value())->context_data();
578 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
582 void Accessors::ScriptContextDataSetter(
583 v8::Local<v8::String> name,
584 v8::Local<v8::Value> value,
585 const v8::PropertyCallbackInfo<void>& info) {
590 Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
591 Isolate* isolate, PropertyAttributes attributes) {
592 Handle<String> name(isolate->factory()->InternalizeOneByteString(
593 STATIC_ASCII_VECTOR("context_data")));
594 return MakeAccessor(isolate,
596 &ScriptContextDataGetter,
597 &ScriptContextDataSetter,
603 // Accessors::ScriptGetEvalFromScript
607 void Accessors::ScriptEvalFromScriptGetter(
608 v8::Local<v8::String> name,
609 const v8::PropertyCallbackInfo<v8::Value>& info) {
610 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
611 HandleScope scope(isolate);
612 Handle<Object> object = Utils::OpenHandle(*info.This());
613 Handle<Script> script(
614 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
615 Handle<Object> result = isolate->factory()->undefined_value();
616 if (!script->eval_from_shared()->IsUndefined()) {
617 Handle<SharedFunctionInfo> eval_from_shared(
618 SharedFunctionInfo::cast(script->eval_from_shared()));
619 if (eval_from_shared->script()->IsScript()) {
620 Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
621 result = Script::GetWrapper(eval_from_script);
625 info.GetReturnValue().Set(Utils::ToLocal(result));
629 void Accessors::ScriptEvalFromScriptSetter(
630 v8::Local<v8::String> name,
631 v8::Local<v8::Value> value,
632 const v8::PropertyCallbackInfo<void>& info) {
637 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
638 Isolate* isolate, PropertyAttributes attributes) {
639 Handle<String> name(isolate->factory()->InternalizeOneByteString(
640 STATIC_ASCII_VECTOR("eval_from_script")));
641 return MakeAccessor(isolate,
643 &ScriptEvalFromScriptGetter,
644 &ScriptEvalFromScriptSetter,
650 // Accessors::ScriptGetEvalFromScriptPosition
654 void Accessors::ScriptEvalFromScriptPositionGetter(
655 v8::Local<v8::String> name,
656 const v8::PropertyCallbackInfo<v8::Value>& info) {
657 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
658 HandleScope scope(isolate);
659 Handle<Object> object = Utils::OpenHandle(*info.This());
660 Handle<Script> script(
661 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
662 Handle<Object> result = isolate->factory()->undefined_value();
663 if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
664 Handle<Code> code(SharedFunctionInfo::cast(
665 script->eval_from_shared())->code());
666 result = Handle<Object>(
667 Smi::FromInt(code->SourcePosition(code->instruction_start() +
668 script->eval_from_instructions_offset()->value())),
671 info.GetReturnValue().Set(Utils::ToLocal(result));
675 void Accessors::ScriptEvalFromScriptPositionSetter(
676 v8::Local<v8::String> name,
677 v8::Local<v8::Value> value,
678 const v8::PropertyCallbackInfo<void>& info) {
683 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
684 Isolate* isolate, PropertyAttributes attributes) {
685 Handle<String> name(isolate->factory()->InternalizeOneByteString(
686 STATIC_ASCII_VECTOR("eval_from_script_position")));
687 return MakeAccessor(isolate,
689 &ScriptEvalFromScriptPositionGetter,
690 &ScriptEvalFromScriptPositionSetter,
696 // Accessors::ScriptGetEvalFromFunctionName
700 void Accessors::ScriptEvalFromFunctionNameGetter(
701 v8::Local<v8::String> name,
702 const v8::PropertyCallbackInfo<v8::Value>& info) {
703 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
704 HandleScope scope(isolate);
705 Handle<Object> object = Utils::OpenHandle(*info.This());
706 Handle<Script> script(
707 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
708 Handle<Object> result;
709 Handle<SharedFunctionInfo> shared(
710 SharedFunctionInfo::cast(script->eval_from_shared()));
711 // Find the name of the function calling eval.
712 if (!shared->name()->IsUndefined()) {
713 result = Handle<Object>(shared->name(), isolate);
715 result = Handle<Object>(shared->inferred_name(), isolate);
717 info.GetReturnValue().Set(Utils::ToLocal(result));
721 void Accessors::ScriptEvalFromFunctionNameSetter(
722 v8::Local<v8::String> name,
723 v8::Local<v8::Value> value,
724 const v8::PropertyCallbackInfo<void>& info) {
729 Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
730 Isolate* isolate, PropertyAttributes attributes) {
731 Handle<String> name(isolate->factory()->InternalizeOneByteString(
732 STATIC_ASCII_VECTOR("eval_from_function_name")));
733 return MakeAccessor(isolate,
735 &ScriptEvalFromFunctionNameGetter,
736 &ScriptEvalFromFunctionNameSetter,
742 // Accessors::FunctionPrototype
745 static Handle<Object> GetFunctionPrototype(Isolate* isolate,
746 Handle<Object> receiver) {
747 Handle<JSFunction> function;
749 DisallowHeapAllocation no_allocation;
750 JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, *receiver);
751 if (function_raw == NULL) return isolate->factory()->undefined_value();
752 while (!function_raw->should_have_prototype()) {
753 function_raw = FindInstanceOf<JSFunction>(isolate,
754 function_raw->GetPrototype());
755 // There has to be one because we hit the getter.
756 ASSERT(function_raw != NULL);
758 function = Handle<JSFunction>(function_raw, isolate);
761 if (!function->has_prototype()) {
762 Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
763 JSFunction::SetPrototype(function, proto);
765 return Handle<Object>(function->prototype(), isolate);
769 static Handle<Object> SetFunctionPrototype(Isolate* isolate,
770 Handle<JSObject> receiver,
771 Handle<Object> value) {
772 Handle<JSFunction> function;
774 DisallowHeapAllocation no_allocation;
775 JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, *receiver);
776 if (function_raw == NULL) return isolate->factory()->undefined_value();
777 function = Handle<JSFunction>(function_raw, isolate);
780 if (!function->should_have_prototype()) {
781 // Since we hit this accessor, object will have no prototype property.
782 MaybeHandle<Object> maybe_result =
783 JSObject::SetLocalPropertyIgnoreAttributes(
784 receiver, isolate->factory()->prototype_string(), value, NONE);
785 return maybe_result.ToHandleChecked();
788 Handle<Object> old_value;
789 bool is_observed = *function == *receiver && function->map()->is_observed();
791 if (function->has_prototype())
792 old_value = handle(function->prototype(), isolate);
794 old_value = isolate->factory()->NewFunctionPrototype(function);
797 JSFunction::SetPrototype(function, value);
798 ASSERT(function->prototype() == *value);
800 if (is_observed && !old_value->SameValue(*value)) {
801 JSObject::EnqueueChangeRecord(
802 function, "update", isolate->factory()->prototype_string(), old_value);
809 Handle<Object> Accessors::FunctionGetPrototype(Handle<JSFunction> function) {
810 return GetFunctionPrototype(function->GetIsolate(), function);
814 Handle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
815 Handle<Object> prototype) {
816 ASSERT(function->should_have_prototype());
817 Isolate* isolate = function->GetIsolate();
818 return SetFunctionPrototype(isolate, function, prototype);
822 void Accessors::FunctionPrototypeGetter(
823 v8::Local<v8::String> name,
824 const v8::PropertyCallbackInfo<v8::Value>& info) {
825 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
826 HandleScope scope(isolate);
827 Handle<Object> object = Utils::OpenHandle(*info.This());
828 Handle<Object> result = GetFunctionPrototype(isolate, object);
829 info.GetReturnValue().Set(Utils::ToLocal(result));
833 void Accessors::FunctionPrototypeSetter(
834 v8::Local<v8::String> name,
835 v8::Local<v8::Value> val,
836 const v8::PropertyCallbackInfo<void>& info) {
837 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
838 HandleScope scope(isolate);
839 Handle<JSObject> object =
840 Handle<JSObject>::cast(Utils::OpenHandle(*info.This()));
841 Handle<Object> value = Utils::OpenHandle(*val);
843 SetFunctionPrototype(isolate, object, value);
847 Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
848 Isolate* isolate, PropertyAttributes attributes) {
849 return MakeAccessor(isolate,
850 isolate->factory()->prototype_string(),
851 &FunctionPrototypeGetter,
852 &FunctionPrototypeSetter,
858 // Accessors::FunctionLength
862 void Accessors::FunctionLengthGetter(
863 v8::Local<v8::String> name,
864 const v8::PropertyCallbackInfo<v8::Value>& info) {
865 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
866 HandleScope scope(isolate);
867 Handle<Object> object = Utils::OpenHandle(*info.This());
868 MaybeHandle<JSFunction> maybe_function;
871 DisallowHeapAllocation no_allocation;
872 JSFunction* function = FindInstanceOf<JSFunction>(isolate, *object);
873 if (function != NULL) maybe_function = Handle<JSFunction>(function);
877 Handle<JSFunction> function;
878 if (maybe_function.ToHandle(&function)) {
879 if (function->shared()->is_compiled()) {
880 length = function->shared()->length();
882 // If the function isn't compiled yet, the length is not computed
883 // correctly yet. Compile it now and return the right length.
884 if (Compiler::EnsureCompiled(function, KEEP_EXCEPTION)) {
885 length = function->shared()->length();
887 if (isolate->has_pending_exception()) {
888 isolate->OptionalRescheduleException(false);
892 Handle<Object> result(Smi::FromInt(length), isolate);
893 info.GetReturnValue().Set(Utils::ToLocal(result));
897 void Accessors::FunctionLengthSetter(
898 v8::Local<v8::String> name,
899 v8::Local<v8::Value> val,
900 const v8::PropertyCallbackInfo<void>& info) {
905 Handle<AccessorInfo> Accessors::FunctionLengthInfo(
906 Isolate* isolate, PropertyAttributes attributes) {
907 return MakeAccessor(isolate,
908 isolate->factory()->length_string(),
909 &FunctionLengthGetter,
910 &FunctionLengthSetter,
916 // Accessors::FunctionName
920 void Accessors::FunctionNameGetter(
921 v8::Local<v8::String> name,
922 const v8::PropertyCallbackInfo<v8::Value>& info) {
923 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
924 HandleScope scope(isolate);
925 Handle<Object> object = Utils::OpenHandle(*info.This());
926 MaybeHandle<JSFunction> maybe_function;
929 DisallowHeapAllocation no_allocation;
930 JSFunction* function = FindInstanceOf<JSFunction>(isolate, *object);
931 if (function != NULL) maybe_function = Handle<JSFunction>(function);
934 Handle<JSFunction> function;
935 Handle<Object> result;
936 if (maybe_function.ToHandle(&function)) {
937 result = Handle<Object>(function->shared()->name(), isolate);
939 result = isolate->factory()->undefined_value();
941 info.GetReturnValue().Set(Utils::ToLocal(result));
945 void Accessors::FunctionNameSetter(
946 v8::Local<v8::String> name,
947 v8::Local<v8::Value> val,
948 const v8::PropertyCallbackInfo<void>& info) {
953 Handle<AccessorInfo> Accessors::FunctionNameInfo(
954 Isolate* isolate, PropertyAttributes attributes) {
955 return MakeAccessor(isolate,
956 isolate->factory()->name_string(),
964 // Accessors::FunctionArguments
968 static Handle<Object> ArgumentsForInlinedFunction(
969 JavaScriptFrame* frame,
970 Handle<JSFunction> inlined_function,
971 int inlined_frame_index) {
972 Isolate* isolate = inlined_function->GetIsolate();
973 Factory* factory = isolate->factory();
974 SlotRefValueBuilder slot_refs(
977 inlined_function->shared()->formal_parameter_count());
979 int args_count = slot_refs.args_length();
980 Handle<JSObject> arguments =
981 factory->NewArgumentsObject(inlined_function, args_count);
982 Handle<FixedArray> array = factory->NewFixedArray(args_count);
983 slot_refs.Prepare(isolate);
984 for (int i = 0; i < args_count; ++i) {
985 Handle<Object> value = slot_refs.GetNext(isolate, 0);
986 array->set(i, *value);
988 slot_refs.Finish(isolate);
989 arguments->set_elements(*array);
991 // Return the freshly allocated arguments object.
996 static int FindFunctionInFrame(JavaScriptFrame* frame,
997 Handle<JSFunction> function) {
998 DisallowHeapAllocation no_allocation;
999 List<JSFunction*> functions(2);
1000 frame->GetFunctions(&functions);
1001 for (int i = functions.length() - 1; i >= 0; i--) {
1002 if (functions[i] == *function) return i;
1008 Handle<Object> GetFunctionArguments(Isolate* isolate,
1009 Handle<JSFunction> function) {
1010 if (function->shared()->native()) return isolate->factory()->null_value();
1012 // Find the top invocation of the function by traversing frames.
1013 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
1014 JavaScriptFrame* frame = it.frame();
1015 int function_index = FindFunctionInFrame(frame, function);
1016 if (function_index < 0) continue;
1018 if (function_index > 0) {
1019 // The function in question was inlined. Inlined functions have the
1020 // correct number of arguments and no allocated arguments object, so
1021 // we can construct a fresh one by interpreting the function's
1022 // deoptimization input data.
1023 return ArgumentsForInlinedFunction(frame, function, function_index);
1026 if (!frame->is_optimized()) {
1027 // If there is an arguments variable in the stack, we return that.
1028 Handle<ScopeInfo> scope_info(function->shared()->scope_info());
1029 int index = scope_info->StackSlotIndex(
1030 isolate->heap()->arguments_string());
1032 Handle<Object> arguments(frame->GetExpression(index), isolate);
1033 if (!arguments->IsArgumentsMarker()) return arguments;
1037 // If there is no arguments variable in the stack or we have an
1038 // optimized frame, we find the frame that holds the actual arguments
1039 // passed to the function.
1040 it.AdvanceToArgumentsFrame();
1043 // Get the number of arguments and construct an arguments object
1044 // mirror for the right frame.
1045 const int length = frame->ComputeParametersCount();
1046 Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
1048 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
1050 // Copy the parameters to the arguments object.
1051 ASSERT(array->length() == length);
1052 for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
1053 arguments->set_elements(*array);
1055 // Return the freshly allocated arguments object.
1059 // No frame corresponding to the given function found. Return null.
1060 return isolate->factory()->null_value();
1064 Handle<Object> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
1065 return GetFunctionArguments(function->GetIsolate(), function);
1069 void Accessors::FunctionArgumentsGetter(
1070 v8::Local<v8::String> name,
1071 const v8::PropertyCallbackInfo<v8::Value>& info) {
1072 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1073 HandleScope scope(isolate);
1074 Handle<Object> object = Utils::OpenHandle(*info.This());
1075 MaybeHandle<JSFunction> maybe_function;
1078 DisallowHeapAllocation no_allocation;
1079 JSFunction* function = FindInstanceOf<JSFunction>(isolate, *object);
1080 if (function != NULL) maybe_function = Handle<JSFunction>(function);
1083 Handle<JSFunction> function;
1084 Handle<Object> result;
1085 if (maybe_function.ToHandle(&function)) {
1086 result = GetFunctionArguments(isolate, function);
1088 result = isolate->factory()->undefined_value();
1090 info.GetReturnValue().Set(Utils::ToLocal(result));
1094 void Accessors::FunctionArgumentsSetter(
1095 v8::Local<v8::String> name,
1096 v8::Local<v8::Value> val,
1097 const v8::PropertyCallbackInfo<void>& info) {
1102 Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
1103 Isolate* isolate, PropertyAttributes attributes) {
1104 return MakeAccessor(isolate,
1105 isolate->factory()->arguments_string(),
1106 &FunctionArgumentsGetter,
1107 &FunctionArgumentsSetter,
1113 // Accessors::FunctionCaller
1117 class FrameFunctionIterator {
1119 FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
1120 : frame_iterator_(isolate),
1125 JSFunction* next() {
1126 if (functions_.length() == 0) return NULL;
1127 JSFunction* next_function = functions_[index_];
1132 return next_function;
1135 // Iterate through functions until the first occurence of 'function'.
1136 // Returns true if 'function' is found, and false if the iterator ends
1137 // without finding it.
1138 bool Find(JSFunction* function) {
1139 JSFunction* next_function;
1141 next_function = next();
1142 if (next_function == function) return true;
1143 } while (next_function != NULL);
1148 void GetFunctions() {
1149 functions_.Rewind(0);
1150 if (frame_iterator_.done()) return;
1151 JavaScriptFrame* frame = frame_iterator_.frame();
1152 frame->GetFunctions(&functions_);
1153 ASSERT(functions_.length() > 0);
1154 frame_iterator_.Advance();
1155 index_ = functions_.length() - 1;
1157 JavaScriptFrameIterator frame_iterator_;
1158 List<JSFunction*> functions_;
1163 MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
1164 Handle<JSFunction> function) {
1165 DisallowHeapAllocation no_allocation;
1166 FrameFunctionIterator it(isolate, no_allocation);
1167 if (function->shared()->native()) {
1168 return MaybeHandle<JSFunction>();
1170 // Find the function from the frames.
1171 if (!it.Find(*function)) {
1172 // No frame corresponding to the given function found. Return null.
1173 return MaybeHandle<JSFunction>();
1175 // Find previously called non-toplevel function.
1179 if (caller == NULL) return MaybeHandle<JSFunction>();
1180 } while (caller->shared()->is_toplevel());
1182 // If caller is a built-in function and caller's caller is also built-in,
1183 // use that instead.
1184 JSFunction* potential_caller = caller;
1185 while (potential_caller != NULL && potential_caller->IsBuiltin()) {
1186 caller = potential_caller;
1187 potential_caller = it.next();
1189 if (!caller->shared()->native() && potential_caller != NULL) {
1190 caller = potential_caller;
1192 // If caller is bound, return null. This is compatible with JSC, and
1193 // allows us to make bound functions use the strict function map
1194 // and its associated throwing caller and arguments.
1195 if (caller->shared()->bound()) {
1196 return MaybeHandle<JSFunction>();
1198 // Censor if the caller is not a sloppy mode function.
1199 // Change from ES5, which used to throw, see:
1200 // https://bugs.ecmascript.org/show_bug.cgi?id=310
1201 if (caller->shared()->strict_mode() == STRICT) {
1202 return MaybeHandle<JSFunction>();
1204 return Handle<JSFunction>(caller);
1208 void Accessors::FunctionCallerGetter(
1209 v8::Local<v8::String> name,
1210 const v8::PropertyCallbackInfo<v8::Value>& info) {
1211 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1212 HandleScope scope(isolate);
1213 Handle<Object> object = Utils::OpenHandle(*info.This());
1214 MaybeHandle<JSFunction> maybe_function;
1216 DisallowHeapAllocation no_allocation;
1217 JSFunction* function = FindInstanceOf<JSFunction>(isolate, *object);
1218 if (function != NULL) maybe_function = Handle<JSFunction>(function);
1220 Handle<JSFunction> function;
1221 Handle<Object> result;
1222 if (maybe_function.ToHandle(&function)) {
1223 MaybeHandle<JSFunction> maybe_caller;
1224 maybe_caller = FindCaller(isolate, function);
1225 Handle<JSFunction> caller;
1226 if (maybe_caller.ToHandle(&caller)) {
1229 result = isolate->factory()->null_value();
1232 result = isolate->factory()->undefined_value();
1234 info.GetReturnValue().Set(Utils::ToLocal(result));
1238 void Accessors::FunctionCallerSetter(
1239 v8::Local<v8::String> name,
1240 v8::Local<v8::Value> val,
1241 const v8::PropertyCallbackInfo<void>& info) {
1246 Handle<AccessorInfo> Accessors::FunctionCallerInfo(
1247 Isolate* isolate, PropertyAttributes attributes) {
1248 return MakeAccessor(isolate,
1249 isolate->factory()->caller_string(),
1250 &FunctionCallerGetter,
1251 &FunctionCallerSetter,
1257 // Accessors::MakeModuleExport
1260 static void ModuleGetExport(
1261 v8::Local<v8::String> property,
1262 const v8::PropertyCallbackInfo<v8::Value>& info) {
1263 JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
1264 Context* context = Context::cast(instance->context());
1265 ASSERT(context->IsModuleContext());
1266 int slot = info.Data()->Int32Value();
1267 Object* value = context->get(slot);
1268 Isolate* isolate = instance->GetIsolate();
1269 if (value->IsTheHole()) {
1270 Handle<String> name = v8::Utils::OpenHandle(*property);
1271 isolate->ScheduleThrow(
1272 *isolate->factory()->NewReferenceError("not_defined",
1273 HandleVector(&name, 1)));
1276 info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate)));
1280 static void ModuleSetExport(
1281 v8::Local<v8::String> property,
1282 v8::Local<v8::Value> value,
1283 const v8::PropertyCallbackInfo<v8::Value>& info) {
1284 JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
1285 Context* context = Context::cast(instance->context());
1286 ASSERT(context->IsModuleContext());
1287 int slot = info.Data()->Int32Value();
1288 Object* old_value = context->get(slot);
1289 if (old_value->IsTheHole()) {
1290 Handle<String> name = v8::Utils::OpenHandle(*property);
1291 Isolate* isolate = instance->GetIsolate();
1292 isolate->ScheduleThrow(
1293 *isolate->factory()->NewReferenceError("not_defined",
1294 HandleVector(&name, 1)));
1297 context->set(slot, *v8::Utils::OpenHandle(*value));
1301 Handle<AccessorInfo> Accessors::MakeModuleExport(
1302 Handle<String> name,
1304 PropertyAttributes attributes) {
1305 Isolate* isolate = name->GetIsolate();
1306 Factory* factory = isolate->factory();
1307 Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
1308 info->set_property_attributes(attributes);
1309 info->set_all_can_read(true);
1310 info->set_all_can_write(true);
1311 info->set_name(*name);
1312 info->set_data(Smi::FromInt(index));
1313 Handle<Object> getter = v8::FromCData(isolate, &ModuleGetExport);
1314 Handle<Object> setter = v8::FromCData(isolate, &ModuleSetExport);
1315 info->set_getter(*getter);
1316 if (!(attributes & ReadOnly)) info->set_setter(*setter);
1321 } } // namespace v8::internal