v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
accessors.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // 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 #include "v8.h"
29 #include "accessors.h"
30 
31 #include "compiler.h"
32 #include "contexts.h"
33 #include "deoptimizer.h"
34 #include "execution.h"
35 #include "factory.h"
36 #include "frames-inl.h"
37 #include "isolate.h"
38 #include "list-inl.h"
39 #include "property-details.h"
40 
41 namespace v8 {
42 namespace internal {
43 
44 
45 template <class C>
46 static C* FindInstanceOf(Isolate* isolate, Object* obj) {
47  for (Object* cur = obj; !cur->IsNull(); cur = cur->GetPrototype(isolate)) {
48  if (Is<C>(cur)) return C::cast(cur);
49  }
50  return NULL;
51 }
52 
53 
54 // Entry point that never should be called.
55 MaybeObject* Accessors::IllegalSetter(Isolate* isolate,
56  JSObject*,
57  Object*,
58  void*) {
59  UNREACHABLE();
60  return NULL;
61 }
62 
63 
64 Object* Accessors::IllegalGetAccessor(Isolate* isolate,
65  Object* object,
66  void*) {
67  UNREACHABLE();
68  return object;
69 }
70 
71 
72 MaybeObject* Accessors::ReadOnlySetAccessor(Isolate* isolate,
73  JSObject*,
74  Object* value,
75  void*) {
76  // According to ECMA-262, section 8.6.2.2, page 28, setting
77  // read-only properties must be silently ignored.
78  return value;
79 }
80 
81 
82 static V8_INLINE bool CheckForName(Handle<String> name,
83  String* property_name,
84  int offset,
85  int* object_offset) {
86  if (name->Equals(property_name)) {
87  *object_offset = offset;
88  return true;
89  }
90  return false;
91 }
92 
93 
94 // Returns true for properties that are accessors to object fields.
95 // If true, *object_offset contains offset of object field.
96 template <class T>
97 bool Accessors::IsJSObjectFieldAccessor(typename T::TypeHandle type,
98  Handle<String> name,
99  int* object_offset) {
100  Isolate* isolate = name->GetIsolate();
101 
102  if (type->Is(T::String())) {
103  return CheckForName(name, isolate->heap()->length_string(),
104  String::kLengthOffset, object_offset);
105  }
106 
107  if (!type->IsClass()) return false;
108  Handle<Map> map = type->AsClass();
109 
110  switch (map->instance_type()) {
111  case JS_ARRAY_TYPE:
112  return
113  CheckForName(name, isolate->heap()->length_string(),
114  JSArray::kLengthOffset, object_offset);
115  case JS_TYPED_ARRAY_TYPE:
116  return
117  CheckForName(name, isolate->heap()->length_string(),
118  JSTypedArray::kLengthOffset, object_offset) ||
119  CheckForName(name, isolate->heap()->byte_length_string(),
120  JSTypedArray::kByteLengthOffset, object_offset) ||
121  CheckForName(name, isolate->heap()->byte_offset_string(),
122  JSTypedArray::kByteOffsetOffset, object_offset);
124  return
125  CheckForName(name, isolate->heap()->byte_length_string(),
126  JSArrayBuffer::kByteLengthOffset, object_offset);
127  case JS_DATA_VIEW_TYPE:
128  return
129  CheckForName(name, isolate->heap()->byte_length_string(),
130  JSDataView::kByteLengthOffset, object_offset) ||
131  CheckForName(name, isolate->heap()->byte_offset_string(),
132  JSDataView::kByteOffsetOffset, object_offset);
133  default:
134  return false;
135  }
136 }
137 
138 
139 template
140 bool Accessors::IsJSObjectFieldAccessor<Type>(Type* type,
142  int* object_offset);
143 
144 
145 template
146 bool Accessors::IsJSObjectFieldAccessor<HeapType>(Handle<HeapType> type,
148  int* object_offset);
149 
150 
151 //
152 // Accessors::ArrayLength
153 //
154 
155 
156 MaybeObject* Accessors::ArrayGetLength(Isolate* isolate,
157  Object* object,
158  void*) {
159  // Traverse the prototype chain until we reach an array.
160  JSArray* holder = FindInstanceOf<JSArray>(isolate, object);
161  return holder == NULL ? Smi::FromInt(0) : holder->length();
162 }
163 
164 
165 // The helper function will 'flatten' Number objects.
166 Handle<Object> Accessors::FlattenNumber(Isolate* isolate,
167  Handle<Object> value) {
168  if (value->IsNumber() || !value->IsJSValue()) return value;
169  Handle<JSValue> wrapper = Handle<JSValue>::cast(value);
170  ASSERT(wrapper->GetIsolate()->context()->native_context()->number_function()->
171  has_initial_map());
172  if (wrapper->map() ==
173  isolate->context()->native_context()->number_function()->initial_map()) {
174  return handle(wrapper->value(), isolate);
175  }
176 
177  return value;
178 }
179 
180 
181 MaybeObject* Accessors::ArraySetLength(Isolate* isolate,
182  JSObject* object_raw,
183  Object* value_raw,
184  void*) {
185  HandleScope scope(isolate);
186  Handle<JSObject> object(object_raw, isolate);
187  Handle<Object> value(value_raw, isolate);
188 
189  // This means one of the object's prototypes is a JSArray and the
190  // object does not have a 'length' property. Calling SetProperty
191  // causes an infinite loop.
192  if (!object->IsJSArray()) {
193  Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(object,
194  isolate->factory()->length_string(), value, NONE);
195  RETURN_IF_EMPTY_HANDLE(isolate, result);
196  return *result;
197  }
198 
199  value = FlattenNumber(isolate, value);
200 
201  Handle<JSArray> array_handle = Handle<JSArray>::cast(object);
202 
203  bool has_exception;
204  Handle<Object> uint32_v =
205  Execution::ToUint32(isolate, value, &has_exception);
206  if (has_exception) return Failure::Exception();
207  Handle<Object> number_v =
208  Execution::ToNumber(isolate, value, &has_exception);
209  if (has_exception) return Failure::Exception();
210 
211  if (uint32_v->Number() == number_v->Number()) {
212  Handle<Object> result = JSArray::SetElementsLength(array_handle, uint32_v);
213  RETURN_IF_EMPTY_HANDLE(isolate, result);
214  return *result;
215  }
216  return isolate->Throw(
217  *isolate->factory()->NewRangeError("invalid_array_length",
218  HandleVector<Object>(NULL, 0)));
219 }
220 
221 
222 const AccessorDescriptor Accessors::ArrayLength = {
223  ArrayGetLength,
224  ArraySetLength,
225  0
226 };
227 
228 
229 //
230 // Accessors::StringLength
231 //
232 
233 
234 MaybeObject* Accessors::StringGetLength(Isolate* isolate,
235  Object* object,
236  void*) {
237  Object* value = object;
238  if (object->IsJSValue()) value = JSValue::cast(object)->value();
239  if (value->IsString()) return Smi::FromInt(String::cast(value)->length());
240  // If object is not a string we return 0 to be compatible with WebKit.
241  // Note: Firefox returns the length of ToString(object).
242  return Smi::FromInt(0);
243 }
244 
245 
246 const AccessorDescriptor Accessors::StringLength = {
247  StringGetLength,
248  IllegalSetter,
249  0
250 };
251 
252 
253 //
254 // Accessors::ScriptSource
255 //
256 
257 
258 MaybeObject* Accessors::ScriptGetSource(Isolate* isolate,
259  Object* object,
260  void*) {
261  Object* script = JSValue::cast(object)->value();
262  return Script::cast(script)->source();
263 }
264 
265 
266 const AccessorDescriptor Accessors::ScriptSource = {
267  ScriptGetSource,
268  IllegalSetter,
269  0
270 };
271 
272 
273 //
274 // Accessors::ScriptName
275 //
276 
277 
278 MaybeObject* Accessors::ScriptGetName(Isolate* isolate,
279  Object* object,
280  void*) {
281  Object* script = JSValue::cast(object)->value();
282  return Script::cast(script)->name();
283 }
284 
285 
286 const AccessorDescriptor Accessors::ScriptName = {
287  ScriptGetName,
288  IllegalSetter,
289  0
290 };
291 
292 
293 //
294 // Accessors::ScriptId
295 //
296 
297 
298 MaybeObject* Accessors::ScriptGetId(Isolate* isolate, Object* object, void*) {
299  Object* script = JSValue::cast(object)->value();
300  return Script::cast(script)->id();
301 }
302 
303 
304 const AccessorDescriptor Accessors::ScriptId = {
305  ScriptGetId,
306  IllegalSetter,
307  0
308 };
309 
310 
311 //
312 // Accessors::ScriptLineOffset
313 //
314 
315 
316 MaybeObject* Accessors::ScriptGetLineOffset(Isolate* isolate,
317  Object* object,
318  void*) {
319  Object* script = JSValue::cast(object)->value();
320  return Script::cast(script)->line_offset();
321 }
322 
323 
324 const AccessorDescriptor Accessors::ScriptLineOffset = {
325  ScriptGetLineOffset,
326  IllegalSetter,
327  0
328 };
329 
330 
331 //
332 // Accessors::ScriptColumnOffset
333 //
334 
335 
336 MaybeObject* Accessors::ScriptGetColumnOffset(Isolate* isolate,
337  Object* object,
338  void*) {
339  Object* script = JSValue::cast(object)->value();
340  return Script::cast(script)->column_offset();
341 }
342 
343 
344 const AccessorDescriptor Accessors::ScriptColumnOffset = {
345  ScriptGetColumnOffset,
346  IllegalSetter,
347  0
348 };
349 
350 
351 //
352 // Accessors::ScriptType
353 //
354 
355 
356 MaybeObject* Accessors::ScriptGetType(Isolate* isolate,
357  Object* object,
358  void*) {
359  Object* script = JSValue::cast(object)->value();
360  return Script::cast(script)->type();
361 }
362 
363 
364 const AccessorDescriptor Accessors::ScriptType = {
365  ScriptGetType,
366  IllegalSetter,
367  0
368 };
369 
370 
371 //
372 // Accessors::ScriptCompilationType
373 //
374 
375 
376 MaybeObject* Accessors::ScriptGetCompilationType(Isolate* isolate,
377  Object* object,
378  void*) {
379  Object* script = JSValue::cast(object)->value();
380  return Smi::FromInt(Script::cast(script)->compilation_type());
381 }
382 
383 
384 const AccessorDescriptor Accessors::ScriptCompilationType = {
385  ScriptGetCompilationType,
386  IllegalSetter,
387  0
388 };
389 
390 
391 //
392 // Accessors::ScriptGetLineEnds
393 //
394 
395 
396 MaybeObject* Accessors::ScriptGetLineEnds(Isolate* isolate,
397  Object* object,
398  void*) {
399  JSValue* wrapper = JSValue::cast(object);
400  HandleScope scope(isolate);
401  Handle<Script> script(Script::cast(wrapper->value()), isolate);
402  InitScriptLineEnds(script);
403  ASSERT(script->line_ends()->IsFixedArray());
404  Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
405  // We do not want anyone to modify this array from JS.
406  ASSERT(*line_ends == isolate->heap()->empty_fixed_array() ||
407  line_ends->map() == isolate->heap()->fixed_cow_array_map());
408  Handle<JSArray> js_array =
409  isolate->factory()->NewJSArrayWithElements(line_ends);
410  return *js_array;
411 }
412 
413 
414 const AccessorDescriptor Accessors::ScriptLineEnds = {
415  ScriptGetLineEnds,
416  IllegalSetter,
417  0
418 };
419 
420 
421 //
422 // Accessors::ScriptGetContextData
423 //
424 
425 
426 MaybeObject* Accessors::ScriptGetContextData(Isolate* isolate,
427  Object* object,
428  void*) {
429  Object* script = JSValue::cast(object)->value();
430  return Script::cast(script)->context_data();
431 }
432 
433 
434 const AccessorDescriptor Accessors::ScriptContextData = {
435  ScriptGetContextData,
436  IllegalSetter,
437  0
438 };
439 
440 
441 //
442 // Accessors::ScriptGetEvalFromScript
443 //
444 
445 
446 MaybeObject* Accessors::ScriptGetEvalFromScript(Isolate* isolate,
447  Object* object,
448  void*) {
449  Object* script = JSValue::cast(object)->value();
450  if (!Script::cast(script)->eval_from_shared()->IsUndefined()) {
451  Handle<SharedFunctionInfo> eval_from_shared(
452  SharedFunctionInfo::cast(Script::cast(script)->eval_from_shared()));
453 
454  if (eval_from_shared->script()->IsScript()) {
455  Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
456  return *GetScriptWrapper(eval_from_script);
457  }
458  }
459  return isolate->heap()->undefined_value();
460 }
461 
462 
463 const AccessorDescriptor Accessors::ScriptEvalFromScript = {
464  ScriptGetEvalFromScript,
465  IllegalSetter,
466  0
467 };
468 
469 
470 //
471 // Accessors::ScriptGetEvalFromScriptPosition
472 //
473 
474 
475 MaybeObject* Accessors::ScriptGetEvalFromScriptPosition(Isolate* isolate,
476  Object* object,
477  void*) {
478  Script* raw_script = Script::cast(JSValue::cast(object)->value());
479  HandleScope scope(isolate);
480  Handle<Script> script(raw_script);
481 
482  // If this is not a script compiled through eval there is no eval position.
483  if (script->compilation_type() != Script::COMPILATION_TYPE_EVAL) {
484  return script->GetHeap()->undefined_value();
485  }
486 
487  // Get the function from where eval was called and find the source position
488  // from the instruction offset.
489  Handle<Code> code(SharedFunctionInfo::cast(
490  script->eval_from_shared())->code());
491  return Smi::FromInt(code->SourcePosition(code->instruction_start() +
492  script->eval_from_instructions_offset()->value()));
493 }
494 
495 
496 const AccessorDescriptor Accessors::ScriptEvalFromScriptPosition = {
497  ScriptGetEvalFromScriptPosition,
498  IllegalSetter,
499  0
500 };
501 
502 
503 //
504 // Accessors::ScriptGetEvalFromFunctionName
505 //
506 
507 
508 MaybeObject* Accessors::ScriptGetEvalFromFunctionName(Isolate* isolate,
509  Object* object,
510  void*) {
511  Object* script = JSValue::cast(object)->value();
512  Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(
513  Script::cast(script)->eval_from_shared()));
514 
515 
516  // Find the name of the function calling eval.
517  if (!shared->name()->IsUndefined()) {
518  return shared->name();
519  } else {
520  return shared->inferred_name();
521  }
522 }
523 
524 
525 const AccessorDescriptor Accessors::ScriptEvalFromFunctionName = {
526  ScriptGetEvalFromFunctionName,
527  IllegalSetter,
528  0
529 };
530 
531 
532 //
533 // Accessors::FunctionPrototype
534 //
535 
536 
538  CALL_HEAP_FUNCTION(function->GetIsolate(),
539  Accessors::FunctionGetPrototype(function->GetIsolate(),
540  *function,
541  NULL),
542  Object);
543 }
544 
545 
547  Handle<Object> prototype) {
548  ASSERT(function->should_have_prototype());
549  CALL_HEAP_FUNCTION(function->GetIsolate(),
550  Accessors::FunctionSetPrototype(function->GetIsolate(),
551  *function,
552  *prototype,
553  NULL),
554  Object);
555 }
556 
557 
558 MaybeObject* Accessors::FunctionGetPrototype(Isolate* isolate,
559  Object* object,
560  void*) {
561  JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, object);
562  if (function_raw == NULL) return isolate->heap()->undefined_value();
563  while (!function_raw->should_have_prototype()) {
564  function_raw = FindInstanceOf<JSFunction>(isolate,
565  function_raw->GetPrototype());
566  // There has to be one because we hit the getter.
567  ASSERT(function_raw != NULL);
568  }
569 
570  if (!function_raw->has_prototype()) {
571  HandleScope scope(isolate);
572  Handle<JSFunction> function(function_raw);
573  Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
574  JSFunction::SetPrototype(function, proto);
575  function_raw = *function;
576  }
577  return function_raw->prototype();
578 }
579 
580 
581 MaybeObject* Accessors::FunctionSetPrototype(Isolate* isolate,
582  JSObject* object_raw,
583  Object* value_raw,
584  void*) {
585  JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, object_raw);
586  if (function_raw == NULL) return isolate->heap()->undefined_value();
587 
588  HandleScope scope(isolate);
589  Handle<JSFunction> function(function_raw, isolate);
590  Handle<JSObject> object(object_raw, isolate);
591  Handle<Object> value(value_raw, isolate);
592  if (!function->should_have_prototype()) {
593  // Since we hit this accessor, object will have no prototype property.
594  Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(object,
595  isolate->factory()->prototype_string(), value, NONE);
596  RETURN_IF_EMPTY_HANDLE(isolate, result);
597  return *result;
598  }
599 
600  Handle<Object> old_value;
601  bool is_observed = *function == *object && function->map()->is_observed();
602  if (is_observed) {
603  if (function->has_prototype())
604  old_value = handle(function->prototype(), isolate);
605  else
606  old_value = isolate->factory()->NewFunctionPrototype(function);
607  }
608 
609  JSFunction::SetPrototype(function, value);
610  ASSERT(function->prototype() == *value);
611 
612  if (is_observed && !old_value->SameValue(*value)) {
614  function, "update", isolate->factory()->prototype_string(), old_value);
615  }
616 
617  return *function;
618 }
619 
620 
621 const AccessorDescriptor Accessors::FunctionPrototype = {
622  FunctionGetPrototype,
623  FunctionSetPrototype,
624  0
625 };
626 
627 
628 //
629 // Accessors::FunctionLength
630 //
631 
632 
633 MaybeObject* Accessors::FunctionGetLength(Isolate* isolate,
634  Object* object,
635  void*) {
636  JSFunction* function = FindInstanceOf<JSFunction>(isolate, object);
637  if (function == NULL) return Smi::FromInt(0);
638  // Check if already compiled.
639  if (function->shared()->is_compiled()) {
640  return Smi::FromInt(function->shared()->length());
641  }
642  // If the function isn't compiled yet, the length is not computed correctly
643  // yet. Compile it now and return the right length.
644  HandleScope scope(isolate);
645  Handle<JSFunction> function_handle(function);
646  if (Compiler::EnsureCompiled(function_handle, KEEP_EXCEPTION)) {
647  return Smi::FromInt(function_handle->shared()->length());
648  }
649  return Failure::Exception();
650 }
651 
652 
653 const AccessorDescriptor Accessors::FunctionLength = {
654  FunctionGetLength,
655  ReadOnlySetAccessor,
656  0
657 };
658 
659 
660 //
661 // Accessors::FunctionName
662 //
663 
664 
665 MaybeObject* Accessors::FunctionGetName(Isolate* isolate,
666  Object* object,
667  void*) {
668  JSFunction* holder = FindInstanceOf<JSFunction>(isolate, object);
669  return holder == NULL
670  ? isolate->heap()->undefined_value()
671  : holder->shared()->name();
672 }
673 
674 
675 const AccessorDescriptor Accessors::FunctionName = {
676  FunctionGetName,
677  ReadOnlySetAccessor,
678  0
679 };
680 
681 
682 //
683 // Accessors::FunctionArguments
684 //
685 
686 
688  CALL_HEAP_FUNCTION(function->GetIsolate(),
689  Accessors::FunctionGetArguments(function->GetIsolate(),
690  *function,
691  NULL),
692  Object);
693 }
694 
695 
696 static MaybeObject* ConstructArgumentsObjectForInlinedFunction(
697  JavaScriptFrame* frame,
698  Handle<JSFunction> inlined_function,
699  int inlined_frame_index) {
700  Isolate* isolate = inlined_function->GetIsolate();
701  Factory* factory = isolate->factory();
702  SlotRefValueBuilder slot_refs(
703  frame,
704  inlined_frame_index,
705  inlined_function->shared()->formal_parameter_count());
706 
707  int args_count = slot_refs.args_length();
708  Handle<JSObject> arguments =
709  factory->NewArgumentsObject(inlined_function, args_count);
710  Handle<FixedArray> array = factory->NewFixedArray(args_count);
711  slot_refs.Prepare(isolate);
712  for (int i = 0; i < args_count; ++i) {
713  Handle<Object> value = slot_refs.GetNext(isolate, 0);
714  array->set(i, *value);
715  }
716  slot_refs.Finish(isolate);
717  arguments->set_elements(*array);
718 
719  // Return the freshly allocated arguments object.
720  return *arguments;
721 }
722 
723 
724 MaybeObject* Accessors::FunctionGetArguments(Isolate* isolate,
725  Object* object,
726  void*) {
727  HandleScope scope(isolate);
728  JSFunction* holder = FindInstanceOf<JSFunction>(isolate, object);
729  if (holder == NULL) return isolate->heap()->undefined_value();
730  Handle<JSFunction> function(holder, isolate);
731 
732  if (function->shared()->native()) return isolate->heap()->null_value();
733  // Find the top invocation of the function by traversing frames.
734  List<JSFunction*> functions(2);
735  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
736  JavaScriptFrame* frame = it.frame();
737  frame->GetFunctions(&functions);
738  for (int i = functions.length() - 1; i >= 0; i--) {
739  // Skip all frames that aren't invocations of the given function.
740  if (functions[i] != *function) continue;
741 
742  if (i > 0) {
743  // The function in question was inlined. Inlined functions have the
744  // correct number of arguments and no allocated arguments object, so
745  // we can construct a fresh one by interpreting the function's
746  // deoptimization input data.
747  return ConstructArgumentsObjectForInlinedFunction(frame, function, i);
748  }
749 
750  if (!frame->is_optimized()) {
751  // If there is an arguments variable in the stack, we return that.
752  Handle<ScopeInfo> scope_info(function->shared()->scope_info());
753  int index = scope_info->StackSlotIndex(
754  isolate->heap()->arguments_string());
755  if (index >= 0) {
756  Handle<Object> arguments(frame->GetExpression(index), isolate);
757  if (!arguments->IsArgumentsMarker()) return *arguments;
758  }
759  }
760 
761  // If there is no arguments variable in the stack or we have an
762  // optimized frame, we find the frame that holds the actual arguments
763  // passed to the function.
764  it.AdvanceToArgumentsFrame();
765  frame = it.frame();
766 
767  // Get the number of arguments and construct an arguments object
768  // mirror for the right frame.
769  const int length = frame->ComputeParametersCount();
770  Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
771  function, length);
772  Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
773 
774  // Copy the parameters to the arguments object.
775  ASSERT(array->length() == length);
776  for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
777  arguments->set_elements(*array);
778 
779  // Return the freshly allocated arguments object.
780  return *arguments;
781  }
782  functions.Rewind(0);
783  }
784 
785  // No frame corresponding to the given function found. Return null.
786  return isolate->heap()->null_value();
787 }
788 
789 
790 const AccessorDescriptor Accessors::FunctionArguments = {
791  FunctionGetArguments,
792  ReadOnlySetAccessor,
793  0
794 };
795 
796 
797 //
798 // Accessors::FunctionCaller
799 //
800 
801 
803  public:
805  : frame_iterator_(isolate),
806  functions_(2),
807  index_(0) {
808  GetFunctions();
809  }
811  if (functions_.length() == 0) return NULL;
812  JSFunction* next_function = functions_[index_];
813  index_--;
814  if (index_ < 0) {
815  GetFunctions();
816  }
817  return next_function;
818  }
819 
820  // Iterate through functions until the first occurence of 'function'.
821  // Returns true if 'function' is found, and false if the iterator ends
822  // without finding it.
823  bool Find(JSFunction* function) {
824  JSFunction* next_function;
825  do {
826  next_function = next();
827  if (next_function == function) return true;
828  } while (next_function != NULL);
829  return false;
830  }
831 
832  private:
833  void GetFunctions() {
834  functions_.Rewind(0);
835  if (frame_iterator_.done()) return;
836  JavaScriptFrame* frame = frame_iterator_.frame();
837  frame->GetFunctions(&functions_);
838  ASSERT(functions_.length() > 0);
839  frame_iterator_.Advance();
840  index_ = functions_.length() - 1;
841  }
842  JavaScriptFrameIterator frame_iterator_;
843  List<JSFunction*> functions_;
844  int index_;
845 };
846 
847 
848 MaybeObject* Accessors::FunctionGetCaller(Isolate* isolate,
849  Object* object,
850  void*) {
851  HandleScope scope(isolate);
852  DisallowHeapAllocation no_allocation;
853  JSFunction* holder = FindInstanceOf<JSFunction>(isolate, object);
854  if (holder == NULL) return isolate->heap()->undefined_value();
855  if (holder->shared()->native()) return isolate->heap()->null_value();
856  Handle<JSFunction> function(holder, isolate);
857 
858  FrameFunctionIterator it(isolate, no_allocation);
859 
860  // Find the function from the frames.
861  if (!it.Find(*function)) {
862  // No frame corresponding to the given function found. Return null.
863  return isolate->heap()->null_value();
864  }
865 
866  // Find previously called non-toplevel function.
867  JSFunction* caller;
868  do {
869  caller = it.next();
870  if (caller == NULL) return isolate->heap()->null_value();
871  } while (caller->shared()->is_toplevel());
872 
873  // If caller is a built-in function and caller's caller is also built-in,
874  // use that instead.
875  JSFunction* potential_caller = caller;
876  while (potential_caller != NULL && potential_caller->IsBuiltin()) {
877  caller = potential_caller;
878  potential_caller = it.next();
879  }
880  if (!caller->shared()->native() && potential_caller != NULL) {
881  caller = potential_caller;
882  }
883  // If caller is bound, return null. This is compatible with JSC, and
884  // allows us to make bound functions use the strict function map
885  // and its associated throwing caller and arguments.
886  if (caller->shared()->bound()) {
887  return isolate->heap()->null_value();
888  }
889  // Censor if the caller is not a sloppy mode function.
890  // Change from ES5, which used to throw, see:
891  // https://bugs.ecmascript.org/show_bug.cgi?id=310
892  if (caller->shared()->strict_mode() == STRICT) {
893  return isolate->heap()->null_value();
894  }
895 
896  return caller;
897 }
898 
899 
900 const AccessorDescriptor Accessors::FunctionCaller = {
901  FunctionGetCaller,
902  ReadOnlySetAccessor,
903  0
904 };
905 
906 
907 //
908 // Accessors::MakeModuleExport
909 //
910 
911 static void ModuleGetExport(
912  v8::Local<v8::String> property,
914  JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
915  Context* context = Context::cast(instance->context());
916  ASSERT(context->IsModuleContext());
917  int slot = info.Data()->Int32Value();
918  Object* value = context->get(slot);
919  Isolate* isolate = instance->GetIsolate();
920  if (value->IsTheHole()) {
921  Handle<String> name = v8::Utils::OpenHandle(*property);
922  isolate->ScheduleThrow(
923  *isolate->factory()->NewReferenceError("not_defined",
924  HandleVector(&name, 1)));
925  return;
926  }
927  info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate)));
928 }
929 
930 
931 static void ModuleSetExport(
932  v8::Local<v8::String> property,
933  v8::Local<v8::Value> value,
935  JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
936  Context* context = Context::cast(instance->context());
937  ASSERT(context->IsModuleContext());
938  int slot = info.Data()->Int32Value();
939  Object* old_value = context->get(slot);
940  if (old_value->IsTheHole()) {
941  Handle<String> name = v8::Utils::OpenHandle(*property);
942  Isolate* isolate = instance->GetIsolate();
943  isolate->ScheduleThrow(
944  *isolate->factory()->NewReferenceError("not_defined",
945  HandleVector(&name, 1)));
946  return;
947  }
948  context->set(slot, *v8::Utils::OpenHandle(*value));
949 }
950 
951 
953  Handle<String> name,
954  int index,
955  PropertyAttributes attributes) {
956  Isolate* isolate = name->GetIsolate();
957  Factory* factory = isolate->factory();
959  info->set_property_attributes(attributes);
960  info->set_all_can_read(true);
961  info->set_all_can_write(true);
962  info->set_name(*name);
963  info->set_data(Smi::FromInt(index));
964  Handle<Object> getter = v8::FromCData(isolate, &ModuleGetExport);
965  Handle<Object> setter = v8::FromCData(isolate, &ModuleSetExport);
966  info->set_getter(*getter);
967  if (!(attributes & ReadOnly)) info->set_setter(*setter);
968  return info;
969 }
970 
971 
972 } } // namespace v8::internal
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
bool Find(JSFunction *function)
Definition: accessors.cc:823
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf map
Definition: flags.cc:350
static Handle< Object > ToNumber(Isolate *isolate, Handle< Object > obj, bool *exc)
Definition: execution.cc:713
static String * cast(Object *obj)
static void SetPrototype(Handle< JSFunction > function, Handle< Object > value)
Definition: objects.cc:9745
static Smi * FromInt(int value)
Definition: objects-inl.h:1209
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
static bool IsJSObjectFieldAccessor(typename T::TypeHandle type, Handle< String > name, int *object_offset)
Definition: accessors.cc:97
kSerializedDataOffset Object
Definition: objects-inl.h:5016
static Failure * Exception()
Definition: objects-inl.h:1244
V8_INLINE Local< Object > Holder() const
Definition: v8.h:6530
static bool EnsureCompiled(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: compiler.cc:687
static const int kByteLengthOffset
Definition: objects.h:9917
void InitScriptLineEnds(Handle< Script > script)
Definition: handles.cc:278
#define ASSERT(condition)
Definition: checks.h:329
static Handle< Object > SetLocalPropertyIgnoreAttributes(Handle< JSObject > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, ValueType value_type=OPTIMAL_REPRESENTATION, StoreMode mode=ALLOW_AS_CONSTANT, ExtensibilityCheck extensibility_check=PERFORM_EXTENSIBILITY_CHECK)
Definition: objects.cc:4141
static Script * cast(Object *obj)
static Context * cast(Object *context)
Definition: contexts.h:244
static SharedFunctionInfo * cast(Object *obj)
static Handle< Object > FunctionSetPrototype(Handle< JSFunction > object, Handle< Object > value)
Definition: accessors.cc:546
Handle< JSObject > NewArgumentsObject(Handle< Object > callee, int length)
Definition: factory.cc:1740
#define RETURN_IF_EMPTY_HANDLE(isolate, call)
Definition: isolate.h:151
Factory * factory()
Definition: isolate.h:995
PropertyAttributes
#define UNREACHABLE()
Definition: checks.h:52
static const int kLengthOffset
Definition: objects.h:8905
#define CALL_HEAP_FUNCTION(ISOLATE, FUNCTION_CALL, TYPE)
Definition: heap-inl.h:679
static const int kByteLengthOffset
Definition: objects.h:9878
Handle< ExecutableAccessorInfo > NewExecutableAccessorInfo()
Definition: factory.cc:690
FrameFunctionIterator(Isolate *isolate, const DisallowHeapAllocation &promise)
Definition: accessors.cc:804
Handle< JSValue > GetScriptWrapper(Handle< Script > script)
Definition: handles.cc:240
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
Handle< FixedArray > NewFixedArray(int size, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:53
V8_INLINE ReturnValue< T > GetReturnValue() const
Definition: v8.h:6536
static const int kByteOffsetOffset
Definition: objects.h:9916
static const int kLengthOffset
Definition: objects.h:9949
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:308
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
static const int kLengthOffset
Definition: objects.h:10076
static Handle< AccessorInfo > MakeModuleExport(Handle< String > name, int index, PropertyAttributes attributes)
Definition: accessors.cc:952
static Handle< Object > FunctionGetArguments(Handle< JSFunction > object)
Definition: accessors.cc:687
v8::internal::Handle< v8::internal::Object > FromCData(v8::internal::Isolate *isolate, T obj)
Definition: api.h:127
static void EnqueueChangeRecord(Handle< JSObject > object, const char *type, Handle< Name > name, Handle< Object > old_value)
Definition: objects.cc:2184
static Handle< Object > SetElementsLength(Handle< JSArray > array, Handle< Object > length)
Definition: objects.cc:11330
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:103
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
Definition: flags.cc:317
bool IsNumber() const
Definition: api.cc:2416
virtual void GetFunctions(List< JSFunction * > *functions)
Definition: frames.cc:785
static JSValue * cast(Object *obj)
Definition: objects-inl.h:5758
static Handle< Object > ToUint32(Isolate *isolate, Handle< Object > obj, bool *exc)
Definition: execution.cc:744
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
Definition: assert-scope.h:214
static FixedArray * cast(Object *obj)
HeapObject * obj
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: v8utils.h:118
static Handle< Object > FunctionGetPrototype(Handle< JSFunction > object)
Definition: accessors.cc:537
static JSModule * cast(Object *obj)
Definition: objects-inl.h:5748
V8_INLINE Local< Value > Data() const
Definition: v8.h:6518
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
#define V8_INLINE
Definition: v8config.h:316