v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
objects.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 
30 #include "api.h"
31 #include "arguments.h"
32 #include "bootstrapper.h"
33 #include "codegen.h"
34 #include "debug.h"
35 #include "deoptimizer.h"
36 #include "date.h"
37 #include "elements.h"
38 #include "execution.h"
39 #include "full-codegen.h"
40 #include "hydrogen.h"
41 #include "objects-inl.h"
42 #include "objects-visiting.h"
43 #include "objects-visiting-inl.h"
44 #include "macro-assembler.h"
45 #include "mark-compact.h"
46 #include "safepoint-table.h"
47 #include "string-stream.h"
48 #include "utils.h"
49 #include "vm-state-inl.h"
50 
51 #ifdef ENABLE_DISASSEMBLER
52 #include "disasm.h"
53 #include "disassembler.h"
54 #endif
55 
56 namespace v8 {
57 namespace internal {
58 
59 
60 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
61  Object* value) {
62  Object* result;
63  { MaybeObject* maybe_result =
64  constructor->GetHeap()->AllocateJSObject(constructor);
65  if (!maybe_result->ToObject(&result)) return maybe_result;
66  }
67  JSValue::cast(result)->set_value(value);
68  return result;
69 }
70 
71 
72 MaybeObject* Object::ToObject(Context* native_context) {
73  if (IsNumber()) {
74  return CreateJSValue(native_context->number_function(), this);
75  } else if (IsBoolean()) {
76  return CreateJSValue(native_context->boolean_function(), this);
77  } else if (IsString()) {
78  return CreateJSValue(native_context->string_function(), this);
79  }
80  ASSERT(IsJSObject());
81  return this;
82 }
83 
84 
85 MaybeObject* Object::ToObject() {
86  if (IsJSReceiver()) {
87  return this;
88  } else if (IsNumber()) {
89  Isolate* isolate = Isolate::Current();
90  Context* native_context = isolate->context()->native_context();
91  return CreateJSValue(native_context->number_function(), this);
92  } else if (IsBoolean()) {
93  Isolate* isolate = HeapObject::cast(this)->GetIsolate();
94  Context* native_context = isolate->context()->native_context();
95  return CreateJSValue(native_context->boolean_function(), this);
96  } else if (IsString()) {
97  Isolate* isolate = HeapObject::cast(this)->GetIsolate();
98  Context* native_context = isolate->context()->native_context();
99  return CreateJSValue(native_context->string_function(), this);
100  }
101 
102  // Throw a type error.
103  return Failure::InternalError();
104 }
105 
106 
108  if (IsTrue()) return this;
109  if (IsFalse()) return this;
110  if (IsSmi()) {
111  return Isolate::Current()->heap()->ToBoolean(Smi::cast(this)->value() != 0);
112  }
113  HeapObject* heap_object = HeapObject::cast(this);
114  if (heap_object->IsUndefined() || heap_object->IsNull()) {
115  return heap_object->GetHeap()->false_value();
116  }
117  // Undetectable object is false
118  if (heap_object->IsUndetectableObject()) {
119  return heap_object->GetHeap()->false_value();
120  }
121  if (heap_object->IsString()) {
122  return heap_object->GetHeap()->ToBoolean(
123  String::cast(this)->length() != 0);
124  }
125  if (heap_object->IsHeapNumber()) {
126  return HeapNumber::cast(this)->HeapNumberToBoolean();
127  }
128  return heap_object->GetHeap()->true_value();
129 }
130 
131 
132 void Object::Lookup(String* name, LookupResult* result) {
133  Object* holder = NULL;
134  if (IsJSReceiver()) {
135  holder = this;
136  } else {
137  Context* native_context = Isolate::Current()->context()->native_context();
138  if (IsNumber()) {
139  holder = native_context->number_function()->instance_prototype();
140  } else if (IsString()) {
141  holder = native_context->string_function()->instance_prototype();
142  } else if (IsBoolean()) {
143  holder = native_context->boolean_function()->instance_prototype();
144  } else {
145  Isolate::Current()->PushStackTraceAndDie(
146  0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001);
147  }
148  }
149  ASSERT(holder != NULL); // Cannot handle null or undefined.
150  JSReceiver::cast(holder)->Lookup(name, result);
151 }
152 
153 
155  String* name,
156  PropertyAttributes* attributes) {
157  LookupResult result(name->GetIsolate());
158  Lookup(name, &result);
159  MaybeObject* value = GetProperty(receiver, &result, name, attributes);
160  ASSERT(*attributes <= ABSENT);
161  return value;
162 }
163 
164 
166  Object* structure,
167  String* name) {
168  Isolate* isolate = name->GetIsolate();
169  // To accommodate both the old and the new api we switch on the
170  // data structure used to store the callbacks. Eventually foreign
171  // callbacks should be phased out.
172  if (structure->IsForeign()) {
173  AccessorDescriptor* callback =
174  reinterpret_cast<AccessorDescriptor*>(
175  Foreign::cast(structure)->foreign_address());
176  MaybeObject* value = (callback->getter)(receiver, callback->data);
178  return value;
179  }
180 
181  // api style callbacks.
182  if (structure->IsAccessorInfo()) {
183  AccessorInfo* data = AccessorInfo::cast(structure);
184  if (!data->IsCompatibleReceiver(receiver)) {
185  Handle<Object> name_handle(name);
186  Handle<Object> receiver_handle(receiver);
187  Handle<Object> args[2] = { name_handle, receiver_handle };
188  Handle<Object> error =
189  isolate->factory()->NewTypeError("incompatible_method_receiver",
190  HandleVector(args,
191  ARRAY_SIZE(args)));
192  return isolate->Throw(*error);
193  }
194  Object* fun_obj = data->getter();
195  v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
196  if (call_fun == NULL) return isolate->heap()->undefined_value();
197  HandleScope scope(isolate);
198  JSObject* self = JSObject::cast(receiver);
199  Handle<String> key(name);
200  LOG(isolate, ApiNamedPropertyAccess("load", self, name));
201  CustomArguments args(isolate, data->data(), self, this);
202  v8::AccessorInfo info(args.end());
203  v8::Handle<v8::Value> result;
204  {
205  // Leaving JavaScript.
206  VMState state(isolate, EXTERNAL);
207  result = call_fun(v8::Utils::ToLocal(key), info);
208  }
210  if (result.IsEmpty()) {
211  return isolate->heap()->undefined_value();
212  }
213  Object* return_value = *v8::Utils::OpenHandle(*result);
214  return_value->VerifyApiCallResultType();
215  return return_value;
216  }
217 
218  // __defineGetter__ callback
219  if (structure->IsAccessorPair()) {
220  Object* getter = AccessorPair::cast(structure)->getter();
221  if (getter->IsSpecFunction()) {
222  // TODO(rossberg): nicer would be to cast to some JSCallable here...
223  return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
224  }
225  // Getter is not a function.
226  return isolate->heap()->undefined_value();
227  }
228 
229  UNREACHABLE();
230  return NULL;
231 }
232 
233 
234 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
235  String* name_raw) {
236  Isolate* isolate = GetIsolate();
237  HandleScope scope(isolate);
238  Handle<Object> receiver(receiver_raw);
239  Handle<Object> name(name_raw);
240 
241  Handle<Object> args[] = { receiver, name };
242  Handle<Object> result = CallTrap(
243  "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
244  if (isolate->has_pending_exception()) return Failure::Exception();
245 
246  return *result;
247 }
248 
249 
251  Isolate* isolate = object->IsHeapObject()
252  ? Handle<HeapObject>::cast(object)->GetIsolate()
253  : Isolate::Current();
254  CALL_HEAP_FUNCTION(isolate, object->GetElement(index), Object);
255 }
256 
257 
258 MaybeObject* JSProxy::GetElementWithHandler(Object* receiver,
259  uint32_t index) {
260  String* name;
261  MaybeObject* maybe = GetHeap()->Uint32ToString(index);
262  if (!maybe->To<String>(&name)) return maybe;
263  return GetPropertyWithHandler(receiver, name);
264 }
265 
266 
268  uint32_t index,
269  Object* value,
270  StrictModeFlag strict_mode) {
271  String* name;
272  MaybeObject* maybe = GetHeap()->Uint32ToString(index);
273  if (!maybe->To<String>(&name)) return maybe;
274  return SetPropertyWithHandler(receiver, name, value, NONE, strict_mode);
275 }
276 
277 
278 bool JSProxy::HasElementWithHandler(uint32_t index) {
279  String* name;
280  MaybeObject* maybe = GetHeap()->Uint32ToString(index);
281  if (!maybe->To<String>(&name)) return maybe;
282  return HasPropertyWithHandler(name);
283 }
284 
285 
287  JSReceiver* getter) {
288  HandleScope scope;
289  Handle<JSReceiver> fun(getter);
290  Handle<Object> self(receiver);
291 #ifdef ENABLE_DEBUGGER_SUPPORT
292  Debug* debug = fun->GetHeap()->isolate()->debug();
293  // Handle stepping into a getter if step into is active.
294  // TODO(rossberg): should this apply to getters that are function proxies?
295  if (debug->StepInActive() && fun->IsJSFunction()) {
296  debug->HandleStepIn(
298  }
299 #endif
300 
301  bool has_pending_exception;
302  Handle<Object> result =
303  Execution::Call(fun, self, 0, NULL, &has_pending_exception, true);
304  // Check for pending exception and return the result.
305  if (has_pending_exception) return Failure::Exception();
306  return *result;
307 }
308 
309 
310 // Only deal with CALLBACKS and INTERCEPTOR
312  Object* receiver,
313  LookupResult* result,
314  String* name,
315  PropertyAttributes* attributes) {
316  if (result->IsProperty()) {
317  switch (result->type()) {
318  case CALLBACKS: {
319  // Only allow API accessors.
320  Object* obj = result->GetCallbackObject();
321  if (obj->IsAccessorInfo()) {
322  AccessorInfo* info = AccessorInfo::cast(obj);
323  if (info->all_can_read()) {
324  *attributes = result->GetAttributes();
325  return result->holder()->GetPropertyWithCallback(
326  receiver, result->GetCallbackObject(), name);
327  }
328  }
329  break;
330  }
331  case NORMAL:
332  case FIELD:
333  case CONSTANT_FUNCTION: {
334  // Search ALL_CAN_READ accessors in prototype chain.
335  LookupResult r(GetIsolate());
336  result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
337  if (r.IsProperty()) {
338  return GetPropertyWithFailedAccessCheck(receiver,
339  &r,
340  name,
341  attributes);
342  }
343  break;
344  }
345  case INTERCEPTOR: {
346  // If the object has an interceptor, try real named properties.
347  // No access check in GetPropertyAttributeWithInterceptor.
348  LookupResult r(GetIsolate());
349  result->holder()->LookupRealNamedProperty(name, &r);
350  if (r.IsProperty()) {
351  return GetPropertyWithFailedAccessCheck(receiver,
352  &r,
353  name,
354  attributes);
355  }
356  break;
357  }
358  default:
359  UNREACHABLE();
360  }
361  }
362 
363  // No accessible property found.
364  *attributes = ABSENT;
365  Heap* heap = name->GetHeap();
367  return heap->undefined_value();
368 }
369 
370 
372  Object* receiver,
373  LookupResult* result,
374  String* name,
375  bool continue_search) {
376  if (result->IsProperty()) {
377  switch (result->type()) {
378  case CALLBACKS: {
379  // Only allow API accessors.
380  Object* obj = result->GetCallbackObject();
381  if (obj->IsAccessorInfo()) {
382  AccessorInfo* info = AccessorInfo::cast(obj);
383  if (info->all_can_read()) {
384  return result->GetAttributes();
385  }
386  }
387  break;
388  }
389 
390  case NORMAL:
391  case FIELD:
392  case CONSTANT_FUNCTION: {
393  if (!continue_search) break;
394  // Search ALL_CAN_READ accessors in prototype chain.
395  LookupResult r(GetIsolate());
396  result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
397  if (r.IsProperty()) {
399  &r,
400  name,
401  continue_search);
402  }
403  break;
404  }
405 
406  case INTERCEPTOR: {
407  // If the object has an interceptor, try real named properties.
408  // No access check in GetPropertyAttributeWithInterceptor.
409  LookupResult r(GetIsolate());
410  if (continue_search) {
411  result->holder()->LookupRealNamedProperty(name, &r);
412  } else {
413  result->holder()->LocalLookupRealNamedProperty(name, &r);
414  }
415  if (!r.IsFound()) break;
417  &r,
418  name,
419  continue_search);
420  }
421 
422  case HANDLER:
423  case TRANSITION:
424  case NONEXISTENT:
425  UNREACHABLE();
426  }
427  }
428 
430  return ABSENT;
431 }
432 
433 
434 Object* JSObject::GetNormalizedProperty(LookupResult* result) {
436  Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
437  if (IsGlobalObject()) {
438  value = JSGlobalPropertyCell::cast(value)->value();
439  }
440  ASSERT(!value->IsJSGlobalPropertyCell());
441  return value;
442 }
443 
444 
445 Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) {
447  if (IsGlobalObject()) {
448  JSGlobalPropertyCell* cell =
450  property_dictionary()->ValueAt(result->GetDictionaryEntry()));
451  cell->set_value(value);
452  } else {
453  property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
454  }
455  return value;
456 }
457 
458 
460  Handle<String> key,
461  Handle<Object> value,
462  PropertyDetails details) {
463  CALL_HEAP_FUNCTION(object->GetIsolate(),
464  object->SetNormalizedProperty(*key, *value, details),
465  Object);
466 }
467 
468 
470  Object* value,
471  PropertyDetails details) {
473  int entry = property_dictionary()->FindEntry(name);
474  if (entry == StringDictionary::kNotFound) {
475  Object* store_value = value;
476  if (IsGlobalObject()) {
477  Heap* heap = name->GetHeap();
478  MaybeObject* maybe_store_value =
479  heap->AllocateJSGlobalPropertyCell(value);
480  if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
481  }
482  Object* dict;
483  { MaybeObject* maybe_dict =
484  property_dictionary()->Add(name, store_value, details);
485  if (!maybe_dict->ToObject(&dict)) return maybe_dict;
486  }
487  set_properties(StringDictionary::cast(dict));
488  return value;
489  }
490 
491  PropertyDetails original_details = property_dictionary()->DetailsAt(entry);
492  int enumeration_index;
493  // Preserve the enumeration index unless the property was deleted.
494  if (original_details.IsDeleted()) {
495  enumeration_index = property_dictionary()->NextEnumerationIndex();
496  property_dictionary()->SetNextEnumerationIndex(enumeration_index + 1);
497  } else {
498  enumeration_index = original_details.dictionary_index();
499  ASSERT(enumeration_index > 0);
500  }
501 
502  details = PropertyDetails(
503  details.attributes(), details.type(), enumeration_index);
504 
505  if (IsGlobalObject()) {
506  JSGlobalPropertyCell* cell =
508  cell->set_value(value);
509  // Please note we have to update the property details.
510  property_dictionary()->DetailsAtPut(entry, details);
511  } else {
512  property_dictionary()->SetEntry(entry, name, value, details);
513  }
514  return value;
515 }
516 
517 
520  StringDictionary* dictionary = property_dictionary();
521  int entry = dictionary->FindEntry(name);
522  if (entry != StringDictionary::kNotFound) {
523  // If we have a global object set the cell to the hole.
524  if (IsGlobalObject()) {
525  PropertyDetails details = dictionary->DetailsAt(entry);
526  if (details.IsDontDelete()) {
527  if (mode != FORCE_DELETION) return GetHeap()->false_value();
528  // When forced to delete global properties, we have to make a
529  // map change to invalidate any ICs that think they can load
530  // from the DontDelete cell without checking if it contains
531  // the hole value.
532  Map* new_map;
533  MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
534  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
535 
536  ASSERT(new_map->is_dictionary_map());
537  set_map(new_map);
538  }
539  JSGlobalPropertyCell* cell =
540  JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
541  cell->set_value(cell->GetHeap()->the_hole_value());
542  dictionary->DetailsAtPut(entry, details.AsDeleted());
543  } else {
544  Object* deleted = dictionary->DeleteProperty(entry, mode);
545  if (deleted == GetHeap()->true_value()) {
546  FixedArray* new_properties = NULL;
547  MaybeObject* maybe_properties = dictionary->Shrink(name);
548  if (!maybe_properties->To(&new_properties)) {
549  return maybe_properties;
550  }
551  set_properties(new_properties);
552  }
553  return deleted;
554  }
555  }
556  return GetHeap()->true_value();
557 }
558 
559 
561  Object* cons_obj = map()->constructor();
562  if (!cons_obj->IsJSFunction())
563  return true;
564  JSFunction* fun = JSFunction::cast(cons_obj);
565  if (!fun->shared()->IsApiFunction())
566  return true;
567  // If the object is fully fast case and has the same map it was
568  // created with then no changes can have been made to it.
569  return map() != fun->initial_map()
571  || !HasFastProperties();
572 }
573 
574 
576  Handle<Object> receiver,
577  LookupResult* result,
578  Handle<String> key,
579  PropertyAttributes* attributes) {
580  Isolate* isolate = object->IsHeapObject()
581  ? Handle<HeapObject>::cast(object)->GetIsolate()
582  : Isolate::Current();
584  isolate,
585  object->GetProperty(*receiver, result, *key, attributes),
586  Object);
587 }
588 
589 
590 MaybeObject* Object::GetProperty(Object* receiver,
591  LookupResult* result,
592  String* name,
593  PropertyAttributes* attributes) {
594  // Make sure that the top context does not change when doing
595  // callbacks or interceptor calls.
596  AssertNoContextChange ncc;
597  Heap* heap = name->GetHeap();
598 
599  // Traverse the prototype chain from the current object (this) to
600  // the holder and check for access rights. This avoids traversing the
601  // objects more than once in case of interceptors, because the
602  // holder will always be the interceptor holder and the search may
603  // only continue with a current object just after the interceptor
604  // holder in the prototype chain.
605  // Proxy handlers do not use the proxy's prototype, so we can skip this.
606  if (!result->IsHandler()) {
607  Object* last = result->IsProperty()
608  ? result->holder()
609  : Object::cast(heap->null_value());
610  ASSERT(this != this->GetPrototype());
611  for (Object* current = this; true; current = current->GetPrototype()) {
612  if (current->IsAccessCheckNeeded()) {
613  // Check if we're allowed to read from the current object. Note
614  // that even though we may not actually end up loading the named
615  // property from the current object, we still check that we have
616  // access to it.
617  JSObject* checked = JSObject::cast(current);
618  if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
619  return checked->GetPropertyWithFailedAccessCheck(receiver,
620  result,
621  name,
622  attributes);
623  }
624  }
625  // Stop traversing the chain once we reach the last object in the
626  // chain; either the holder of the result or null in case of an
627  // absent property.
628  if (current == last) break;
629  }
630  }
631 
632  if (!result->IsProperty()) {
633  *attributes = ABSENT;
634  return heap->undefined_value();
635  }
636  *attributes = result->GetAttributes();
637  Object* value;
638  switch (result->type()) {
639  case NORMAL:
640  value = result->holder()->GetNormalizedProperty(result);
641  ASSERT(!value->IsTheHole() || result->IsReadOnly());
642  return value->IsTheHole() ? heap->undefined_value() : value;
643  case FIELD:
644  value = result->holder()->FastPropertyAt(result->GetFieldIndex());
645  ASSERT(!value->IsTheHole() || result->IsReadOnly());
646  return value->IsTheHole() ? heap->undefined_value() : value;
647  case CONSTANT_FUNCTION:
648  return result->GetConstantFunction();
649  case CALLBACKS:
650  return result->holder()->GetPropertyWithCallback(
651  receiver, result->GetCallbackObject(), name);
652  case HANDLER:
653  return result->proxy()->GetPropertyWithHandler(receiver, name);
654  case INTERCEPTOR:
655  return result->holder()->GetPropertyWithInterceptor(
656  receiver, name, attributes);
657  case TRANSITION:
658  case NONEXISTENT:
659  UNREACHABLE();
660  break;
661  }
662  UNREACHABLE();
663  return NULL;
664 }
665 
666 
667 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
668  Heap* heap = IsSmi()
669  ? Isolate::Current()->heap()
670  : HeapObject::cast(this)->GetHeap();
671  Object* holder = this;
672 
673  // Iterate up the prototype chain until an element is found or the null
674  // prototype is encountered.
675  for (holder = this;
676  holder != heap->null_value();
677  holder = holder->GetPrototype()) {
678  if (!holder->IsJSObject()) {
679  Isolate* isolate = heap->isolate();
680  Context* native_context = isolate->context()->native_context();
681  if (holder->IsNumber()) {
682  holder = native_context->number_function()->instance_prototype();
683  } else if (holder->IsString()) {
684  holder = native_context->string_function()->instance_prototype();
685  } else if (holder->IsBoolean()) {
686  holder = native_context->boolean_function()->instance_prototype();
687  } else if (holder->IsJSProxy()) {
688  return JSProxy::cast(holder)->GetElementWithHandler(receiver, index);
689  } else {
690  // Undefined and null have no indexed properties.
691  ASSERT(holder->IsUndefined() || holder->IsNull());
692  return heap->undefined_value();
693  }
694  }
695 
696  // Inline the case for JSObjects. Doing so significantly improves the
697  // performance of fetching elements where checking the prototype chain is
698  // necessary.
699  JSObject* js_object = JSObject::cast(holder);
700 
701  // Check access rights if needed.
702  if (js_object->IsAccessCheckNeeded()) {
703  Isolate* isolate = heap->isolate();
704  if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
705  isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
706  return heap->undefined_value();
707  }
708  }
709 
710  if (js_object->HasIndexedInterceptor()) {
711  return js_object->GetElementWithInterceptor(receiver, index);
712  }
713 
714  if (js_object->elements() != heap->empty_fixed_array()) {
715  MaybeObject* result = js_object->GetElementsAccessor()->Get(
716  receiver, js_object, index);
717  if (result != heap->the_hole_value()) return result;
718  }
719  }
720 
721  return heap->undefined_value();
722 }
723 
724 
726  if (IsSmi()) {
727  Heap* heap = Isolate::Current()->heap();
728  Context* context = heap->isolate()->context()->native_context();
729  return context->number_function()->instance_prototype();
730  }
731 
732  HeapObject* heap_object = HeapObject::cast(this);
733 
734  // The object is either a number, a string, a boolean,
735  // a real JS object, or a Harmony proxy.
736  if (heap_object->IsJSReceiver()) {
737  return heap_object->map()->prototype();
738  }
739  Heap* heap = heap_object->GetHeap();
740  Context* context = heap->isolate()->context()->native_context();
741 
742  if (heap_object->IsHeapNumber()) {
743  return context->number_function()->instance_prototype();
744  }
745  if (heap_object->IsString()) {
746  return context->string_function()->instance_prototype();
747  }
748  if (heap_object->IsBoolean()) {
749  return context->boolean_function()->instance_prototype();
750  } else {
751  return heap->null_value();
752  }
753 }
754 
755 
757  // The object is either a number, a string, an odd-ball,
758  // a real JS object, or a Harmony proxy.
759  if (IsNumber()) {
760  uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
761  return Smi::FromInt(hash & Smi::kMaxValue);
762  }
763  if (IsString()) {
764  uint32_t hash = String::cast(this)->Hash();
765  return Smi::FromInt(hash);
766  }
767  if (IsOddball()) {
768  uint32_t hash = Oddball::cast(this)->to_string()->Hash();
769  return Smi::FromInt(hash);
770  }
771  if (IsJSReceiver()) {
772  return JSReceiver::cast(this)->GetIdentityHash(flag);
773  }
774 
775  UNREACHABLE();
776  return Smi::FromInt(0);
777 }
778 
779 
780 bool Object::SameValue(Object* other) {
781  if (other == this) return true;
782 
783  // The object is either a number, a string, an odd-ball,
784  // a real JS object, or a Harmony proxy.
785  if (IsNumber() && other->IsNumber()) {
786  double this_value = Number();
787  double other_value = other->Number();
788  return (this_value == other_value) ||
789  (isnan(this_value) && isnan(other_value));
790  }
791  if (IsString() && other->IsString()) {
792  return String::cast(this)->Equals(String::cast(other));
793  }
794  return false;
795 }
796 
797 
798 void Object::ShortPrint(FILE* out) {
799  HeapStringAllocator allocator;
800  StringStream accumulator(&allocator);
801  ShortPrint(&accumulator);
802  accumulator.OutputToFile(out);
803 }
804 
805 
806 void Object::ShortPrint(StringStream* accumulator) {
807  if (IsSmi()) {
808  Smi::cast(this)->SmiPrint(accumulator);
809  } else if (IsFailure()) {
810  Failure::cast(this)->FailurePrint(accumulator);
811  } else {
812  HeapObject::cast(this)->HeapObjectShortPrint(accumulator);
813  }
814 }
815 
816 
817 void Smi::SmiPrint(FILE* out) {
818  PrintF(out, "%d", value());
819 }
820 
821 
822 void Smi::SmiPrint(StringStream* accumulator) {
823  accumulator->Add("%d", value());
824 }
825 
826 
828  accumulator->Add("Failure(%p)", reinterpret_cast<void*>(value()));
829 }
830 
831 
832 void Failure::FailurePrint(FILE* out) {
833  PrintF(out, "Failure(%p)", reinterpret_cast<void*>(value()));
834 }
835 
836 
837 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
838 // English? Returns false for non-ASCII or words that don't start with
839 // a capital letter. The a/an rule follows pronunciation in English.
840 // We don't use the BBC's overcorrect "an historic occasion" though if
841 // you speak a dialect you may well say "an 'istoric occasion".
842 static bool AnWord(String* str) {
843  if (str->length() == 0) return false; // A nothing.
844  int c0 = str->Get(0);
845  int c1 = str->length() > 1 ? str->Get(1) : 0;
846  if (c0 == 'U') {
847  if (c1 > 'Z') {
848  return true; // An Umpire, but a UTF8String, a U.
849  }
850  } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
851  return true; // An Ape, an ABCBook.
852  } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
853  (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
854  c0 == 'S' || c0 == 'X')) {
855  return true; // An MP3File, an M.
856  }
857  return false;
858 }
859 
860 
861 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) {
862 #ifdef DEBUG
863  // Do not attempt to flatten in debug mode when allocation is not
864  // allowed. This is to avoid an assertion failure when allocating.
865  // Flattening strings is the only case where we always allow
866  // allocation because no GC is performed if the allocation fails.
867  if (!HEAP->IsAllocationAllowed()) return this;
868 #endif
869 
870  Heap* heap = GetHeap();
871  switch (StringShape(this).representation_tag()) {
872  case kConsStringTag: {
873  ConsString* cs = ConsString::cast(this);
874  if (cs->second()->length() == 0) {
875  return cs->first();
876  }
877  // There's little point in putting the flat string in new space if the
878  // cons string is in old space. It can never get GCed until there is
879  // an old space GC.
880  PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
881  int len = length();
882  Object* object;
883  String* result;
884  if (IsAsciiRepresentation()) {
885  { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure);
886  if (!maybe_object->ToObject(&object)) return maybe_object;
887  }
888  result = String::cast(object);
889  String* first = cs->first();
890  int first_length = first->length();
891  char* dest = SeqAsciiString::cast(result)->GetChars();
892  WriteToFlat(first, dest, 0, first_length);
893  String* second = cs->second();
894  WriteToFlat(second,
895  dest + first_length,
896  0,
897  len - first_length);
898  } else {
899  { MaybeObject* maybe_object =
900  heap->AllocateRawTwoByteString(len, tenure);
901  if (!maybe_object->ToObject(&object)) return maybe_object;
902  }
903  result = String::cast(object);
904  uc16* dest = SeqTwoByteString::cast(result)->GetChars();
905  String* first = cs->first();
906  int first_length = first->length();
907  WriteToFlat(first, dest, 0, first_length);
908  String* second = cs->second();
909  WriteToFlat(second,
910  dest + first_length,
911  0,
912  len - first_length);
913  }
914  cs->set_first(result);
915  cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER);
916  return result;
917  }
918  default:
919  return this;
920  }
921 }
922 
923 
925  // Externalizing twice leaks the external resource, so it's
926  // prohibited by the API.
927  ASSERT(!this->IsExternalString());
928 #ifdef DEBUG
930  // Assert that the resource and the string are equivalent.
931  ASSERT(static_cast<size_t>(this->length()) == resource->length());
932  ScopedVector<uc16> smart_chars(this->length());
933  String::WriteToFlat(this, smart_chars.start(), 0, this->length());
934  ASSERT(memcmp(smart_chars.start(),
935  resource->data(),
936  resource->length() * sizeof(smart_chars[0])) == 0);
937  }
938 #endif // DEBUG
939  Heap* heap = GetHeap();
940  int size = this->Size(); // Byte size of the original string.
941  if (size < ExternalString::kShortSize) {
942  return false;
943  }
944  bool is_ascii = this->IsAsciiRepresentation();
945  bool is_symbol = this->IsSymbol();
946 
947  // Morph the object to an external string by adjusting the map and
948  // reinitializing the fields.
949  if (size >= ExternalString::kSize) {
951  is_symbol
952  ? (is_ascii ? heap->external_symbol_with_ascii_data_map()
953  : heap->external_symbol_map())
954  : (is_ascii ? heap->external_string_with_ascii_data_map()
955  : heap->external_string_map()));
956  } else {
958  is_symbol
959  ? (is_ascii ? heap->short_external_symbol_with_ascii_data_map()
960  : heap->short_external_symbol_map())
961  : (is_ascii ? heap->short_external_string_with_ascii_data_map()
962  : heap->short_external_string_map()));
963  }
965  self->set_resource(resource);
966  if (is_symbol) self->Hash(); // Force regeneration of the hash value.
967 
968  // Fill the remainder of the string with dead wood.
969  int new_size = this->Size(); // Byte size of the external String object.
970  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
973  new_size - size);
974  }
975  return true;
976 }
977 
978 
980 #ifdef DEBUG
982  // Assert that the resource and the string are equivalent.
983  ASSERT(static_cast<size_t>(this->length()) == resource->length());
984  ScopedVector<char> smart_chars(this->length());
985  String::WriteToFlat(this, smart_chars.start(), 0, this->length());
986  ASSERT(memcmp(smart_chars.start(),
987  resource->data(),
988  resource->length() * sizeof(smart_chars[0])) == 0);
989  }
990 #endif // DEBUG
991  Heap* heap = GetHeap();
992  int size = this->Size(); // Byte size of the original string.
993  if (size < ExternalString::kShortSize) {
994  return false;
995  }
996  bool is_symbol = this->IsSymbol();
997 
998  // Morph the object to an external string by adjusting the map and
999  // reinitializing the fields. Use short version if space is limited.
1000  if (size >= ExternalString::kSize) {
1002  is_symbol ? heap->external_ascii_symbol_map()
1003  : heap->external_ascii_string_map());
1004  } else {
1006  is_symbol ? heap->short_external_ascii_symbol_map()
1007  : heap->short_external_ascii_string_map());
1008  }
1010  self->set_resource(resource);
1011  if (is_symbol) self->Hash(); // Force regeneration of the hash value.
1012 
1013  // Fill the remainder of the string with dead wood.
1014  int new_size = this->Size(); // Byte size of the external String object.
1015  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1018  new_size - size);
1019  }
1020  return true;
1021 }
1022 
1023 
1025  int len = length();
1026  if (len > kMaxShortPrintLength) {
1027  accumulator->Add("<Very long string[%u]>", len);
1028  return;
1029  }
1030 
1031  if (!LooksValid()) {
1032  accumulator->Add("<Invalid String>");
1033  return;
1034  }
1035 
1036  StringInputBuffer buf(this);
1037 
1038  bool truncated = false;
1039  if (len > kMaxShortPrintLength) {
1040  len = kMaxShortPrintLength;
1041  truncated = true;
1042  }
1043  bool ascii = true;
1044  for (int i = 0; i < len; i++) {
1045  int c = buf.GetNext();
1046 
1047  if (c < 32 || c >= 127) {
1048  ascii = false;
1049  }
1050  }
1051  buf.Reset(this);
1052  if (ascii) {
1053  accumulator->Add("<String[%u]: ", length());
1054  for (int i = 0; i < len; i++) {
1055  accumulator->Put(buf.GetNext());
1056  }
1057  accumulator->Put('>');
1058  } else {
1059  // Backslash indicates that the string contains control
1060  // characters and that backslashes are therefore escaped.
1061  accumulator->Add("<String[%u]\\: ", length());
1062  for (int i = 0; i < len; i++) {
1063  int c = buf.GetNext();
1064  if (c == '\n') {
1065  accumulator->Add("\\n");
1066  } else if (c == '\r') {
1067  accumulator->Add("\\r");
1068  } else if (c == '\\') {
1069  accumulator->Add("\\\\");
1070  } else if (c < 32 || c > 126) {
1071  accumulator->Add("\\x%02x", c);
1072  } else {
1073  accumulator->Put(c);
1074  }
1075  }
1076  if (truncated) {
1077  accumulator->Put('.');
1078  accumulator->Put('.');
1079  accumulator->Put('.');
1080  }
1081  accumulator->Put('>');
1082  }
1083  return;
1084 }
1085 
1086 
1088  switch (map()->instance_type()) {
1089  case JS_ARRAY_TYPE: {
1090  double length = JSArray::cast(this)->length()->IsUndefined()
1091  ? 0
1092  : JSArray::cast(this)->length()->Number();
1093  accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1094  break;
1095  }
1096  case JS_WEAK_MAP_TYPE: {
1097  accumulator->Add("<JS WeakMap>");
1098  break;
1099  }
1100  case JS_REGEXP_TYPE: {
1101  accumulator->Add("<JS RegExp>");
1102  break;
1103  }
1104  case JS_FUNCTION_TYPE: {
1105  Object* fun_name = JSFunction::cast(this)->shared()->name();
1106  bool printed = false;
1107  if (fun_name->IsString()) {
1108  String* str = String::cast(fun_name);
1109  if (str->length() > 0) {
1110  accumulator->Add("<JS Function ");
1111  accumulator->Put(str);
1112  accumulator->Put('>');
1113  printed = true;
1114  }
1115  }
1116  if (!printed) {
1117  accumulator->Add("<JS Function>");
1118  }
1119  break;
1120  }
1121  // All other JSObjects are rather similar to each other (JSObject,
1122  // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1123  default: {
1124  Map* map_of_this = map();
1125  Heap* heap = GetHeap();
1126  Object* constructor = map_of_this->constructor();
1127  bool printed = false;
1128  if (constructor->IsHeapObject() &&
1129  !heap->Contains(HeapObject::cast(constructor))) {
1130  accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1131  } else {
1132  bool global_object = IsJSGlobalProxy();
1133  if (constructor->IsJSFunction()) {
1134  if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1135  accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1136  } else {
1138  JSFunction::cast(constructor)->shared()->name();
1139  if (constructor_name->IsString()) {
1140  String* str = String::cast(constructor_name);
1141  if (str->length() > 0) {
1142  bool vowel = AnWord(str);
1143  accumulator->Add("<%sa%s ",
1144  global_object ? "Global Object: " : "",
1145  vowel ? "n" : "");
1146  accumulator->Put(str);
1147  printed = true;
1148  }
1149  }
1150  }
1151  }
1152  if (!printed) {
1153  accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1154  }
1155  }
1156  if (IsJSValue()) {
1157  accumulator->Add(" value = ");
1158  JSValue::cast(this)->value()->ShortPrint(accumulator);
1159  }
1160  accumulator->Put('>');
1161  break;
1162  }
1163  }
1164 }
1165 
1166 
1168  FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
1169  ElementsKind to_kind, FixedArrayBase* to_elements) {
1170  if (from_kind != to_kind) {
1171  PrintF(file, "elements transition [");
1172  PrintElementsKind(file, from_kind);
1173  PrintF(file, " -> ");
1174  PrintElementsKind(file, to_kind);
1175  PrintF(file, "] in ");
1176  JavaScriptFrame::PrintTop(file, false, true);
1177  PrintF(file, " for ");
1178  ShortPrint(file);
1179  PrintF(file, " from ");
1180  from_elements->ShortPrint(file);
1181  PrintF(file, " to ");
1182  to_elements->ShortPrint(file);
1183  PrintF(file, "\n");
1184  }
1185 }
1186 
1187 
1189  Heap* heap = GetHeap();
1190  if (!heap->Contains(this)) {
1191  accumulator->Add("!!!INVALID POINTER!!!");
1192  return;
1193  }
1194  if (!heap->Contains(map())) {
1195  accumulator->Add("!!!INVALID MAP!!!");
1196  return;
1197  }
1198 
1199  accumulator->Add("%p ", this);
1200 
1201  if (IsString()) {
1202  String::cast(this)->StringShortPrint(accumulator);
1203  return;
1204  }
1205  if (IsJSObject()) {
1206  JSObject::cast(this)->JSObjectShortPrint(accumulator);
1207  return;
1208  }
1209  switch (map()->instance_type()) {
1210  case MAP_TYPE:
1211  accumulator->Add("<Map(elements=%u)>", Map::cast(this)->elements_kind());
1212  break;
1213  case FIXED_ARRAY_TYPE:
1214  accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
1215  break;
1217  accumulator->Add("<FixedDoubleArray[%u]>",
1218  FixedDoubleArray::cast(this)->length());
1219  break;
1220  case BYTE_ARRAY_TYPE:
1221  accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
1222  break;
1223  case FREE_SPACE_TYPE:
1224  accumulator->Add("<FreeSpace[%u]>", FreeSpace::cast(this)->Size());
1225  break;
1227  accumulator->Add("<ExternalPixelArray[%u]>",
1228  ExternalPixelArray::cast(this)->length());
1229  break;
1231  accumulator->Add("<ExternalByteArray[%u]>",
1232  ExternalByteArray::cast(this)->length());
1233  break;
1235  accumulator->Add("<ExternalUnsignedByteArray[%u]>",
1236  ExternalUnsignedByteArray::cast(this)->length());
1237  break;
1239  accumulator->Add("<ExternalShortArray[%u]>",
1240  ExternalShortArray::cast(this)->length());
1241  break;
1243  accumulator->Add("<ExternalUnsignedShortArray[%u]>",
1244  ExternalUnsignedShortArray::cast(this)->length());
1245  break;
1247  accumulator->Add("<ExternalIntArray[%u]>",
1248  ExternalIntArray::cast(this)->length());
1249  break;
1251  accumulator->Add("<ExternalUnsignedIntArray[%u]>",
1252  ExternalUnsignedIntArray::cast(this)->length());
1253  break;
1255  accumulator->Add("<ExternalFloatArray[%u]>",
1256  ExternalFloatArray::cast(this)->length());
1257  break;
1259  accumulator->Add("<ExternalDoubleArray[%u]>",
1260  ExternalDoubleArray::cast(this)->length());
1261  break;
1263  accumulator->Add("<SharedFunctionInfo>");
1264  break;
1266  accumulator->Add("<JSMessageObject>");
1267  break;
1268 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1269  case NAME##_TYPE: \
1270  accumulator->Put('<'); \
1271  accumulator->Add(#Name); \
1272  accumulator->Put('>'); \
1273  break;
1275 #undef MAKE_STRUCT_CASE
1276  case CODE_TYPE:
1277  accumulator->Add("<Code>");
1278  break;
1279  case ODDBALL_TYPE: {
1280  if (IsUndefined())
1281  accumulator->Add("<undefined>");
1282  else if (IsTheHole())
1283  accumulator->Add("<the hole>");
1284  else if (IsNull())
1285  accumulator->Add("<null>");
1286  else if (IsTrue())
1287  accumulator->Add("<true>");
1288  else if (IsFalse())
1289  accumulator->Add("<false>");
1290  else
1291  accumulator->Add("<Odd Oddball>");
1292  break;
1293  }
1294  case HEAP_NUMBER_TYPE:
1295  accumulator->Add("<Number: ");
1296  HeapNumber::cast(this)->HeapNumberPrint(accumulator);
1297  accumulator->Put('>');
1298  break;
1299  case JS_PROXY_TYPE:
1300  accumulator->Add("<JSProxy>");
1301  break;
1303  accumulator->Add("<JSFunctionProxy>");
1304  break;
1305  case FOREIGN_TYPE:
1306  accumulator->Add("<Foreign>");
1307  break;
1309  accumulator->Add("Cell for ");
1310  JSGlobalPropertyCell::cast(this)->value()->ShortPrint(accumulator);
1311  break;
1312  default:
1313  accumulator->Add("<Other heap object (%d)>", map()->instance_type());
1314  break;
1315  }
1316 }
1317 
1318 
1319 void HeapObject::Iterate(ObjectVisitor* v) {
1320  // Handle header
1322  // Handle object body
1323  Map* m = map();
1324  IterateBody(m->instance_type(), SizeFromMap(m), v);
1325 }
1326 
1327 
1328 void HeapObject::IterateBody(InstanceType type, int object_size,
1329  ObjectVisitor* v) {
1330  // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1331  // During GC, the map pointer field is encoded.
1332  if (type < FIRST_NONSTRING_TYPE) {
1333  switch (type & kStringRepresentationMask) {
1334  case kSeqStringTag:
1335  break;
1336  case kConsStringTag:
1338  break;
1339  case kSlicedStringTag:
1341  break;
1342  case kExternalStringTag:
1343  if ((type & kStringEncodingMask) == kAsciiStringTag) {
1344  reinterpret_cast<ExternalAsciiString*>(this)->
1345  ExternalAsciiStringIterateBody(v);
1346  } else {
1347  reinterpret_cast<ExternalTwoByteString*>(this)->
1348  ExternalTwoByteStringIterateBody(v);
1349  }
1350  break;
1351  }
1352  return;
1353  }
1354 
1355  switch (type) {
1356  case FIXED_ARRAY_TYPE:
1357  FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1358  break;
1360  break;
1361  case JS_OBJECT_TYPE:
1363  case JS_MODULE_TYPE:
1364  case JS_VALUE_TYPE:
1365  case JS_DATE_TYPE:
1366  case JS_ARRAY_TYPE:
1367  case JS_SET_TYPE:
1368  case JS_MAP_TYPE:
1369  case JS_WEAK_MAP_TYPE:
1370  case JS_REGEXP_TYPE:
1371  case JS_GLOBAL_PROXY_TYPE:
1372  case JS_GLOBAL_OBJECT_TYPE:
1375  JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1376  break;
1377  case JS_FUNCTION_TYPE:
1378  reinterpret_cast<JSFunction*>(this)
1379  ->JSFunctionIterateBody(object_size, v);
1380  break;
1381  case ODDBALL_TYPE:
1383  break;
1384  case JS_PROXY_TYPE:
1386  break;
1389  break;
1390  case FOREIGN_TYPE:
1391  reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1392  break;
1393  case MAP_TYPE:
1395  break;
1396  case CODE_TYPE:
1397  reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1398  break;
1401  break;
1402  case HEAP_NUMBER_TYPE:
1403  case FILLER_TYPE:
1404  case BYTE_ARRAY_TYPE:
1405  case FREE_SPACE_TYPE:
1415  break;
1418  break;
1419  }
1420 
1421 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1422  case NAME##_TYPE:
1424 #undef MAKE_STRUCT_CASE
1425  StructBodyDescriptor::IterateBody(this, object_size, v);
1426  break;
1427  default:
1428  PrintF("Unknown type: %d\n", type);
1429  UNREACHABLE();
1430  }
1431 }
1432 
1433 
1435  // NaN, +0, and -0 should return the false object
1436 #if __BYTE_ORDER == __LITTLE_ENDIAN
1438 #elif __BYTE_ORDER == __BIG_ENDIAN
1440 #endif
1441  u.d = value();
1442  if (u.bits.exp == 2047) {
1443  // Detect NaN for IEEE double precision floating point.
1444  if ((u.bits.man_low | u.bits.man_high) != 0)
1445  return GetHeap()->false_value();
1446  }
1447  if (u.bits.exp == 0) {
1448  // Detect +0, and -0 for IEEE double precision floating point.
1449  if ((u.bits.man_low | u.bits.man_high) == 0)
1450  return GetHeap()->false_value();
1451  }
1452  return GetHeap()->true_value();
1453 }
1454 
1455 
1457  PrintF(out, "%.16g", Number());
1458 }
1459 
1460 
1462  // The Windows version of vsnprintf can allocate when printing a %g string
1463  // into a buffer that may not be big enough. We don't want random memory
1464  // allocation when producing post-crash stack traces, so we print into a
1465  // buffer that is plenty big enough for any floating point number, then
1466  // print that using vsnprintf (which may truncate but never allocate if
1467  // there is no more space in the buffer).
1469  OS::SNPrintF(buffer, "%.16g", Number());
1470  accumulator->Add("%s", buffer.start());
1471 }
1472 
1473 
1475  if (IsJSFunction() && IsJSFunctionProxy()) {
1476  return GetHeap()->function_class_symbol();
1477  }
1478  if (map()->constructor()->IsJSFunction()) {
1479  JSFunction* constructor = JSFunction::cast(map()->constructor());
1480  return String::cast(constructor->shared()->instance_class_name());
1481  }
1482  // If the constructor is not present, return "Object".
1483  return GetHeap()->Object_symbol();
1484 }
1485 
1486 
1488  if (map()->constructor()->IsJSFunction()) {
1489  JSFunction* constructor = JSFunction::cast(map()->constructor());
1490  String* name = String::cast(constructor->shared()->name());
1491  if (name->length() > 0) return name;
1492  String* inferred_name = constructor->shared()->inferred_name();
1493  if (inferred_name->length() > 0) return inferred_name;
1494  Object* proto = GetPrototype();
1495  if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1496  }
1497  // TODO(rossberg): what about proxies?
1498  // If the constructor is not present, return "Object".
1499  return GetHeap()->Object_symbol();
1500 }
1501 
1502 
1504  String* name,
1505  Object* value,
1506  int field_index) {
1507  if (map()->unused_property_fields() == 0) {
1508  int new_unused = new_map->unused_property_fields();
1509  FixedArray* values;
1510  { MaybeObject* maybe_values =
1511  properties()->CopySize(properties()->length() + new_unused + 1);
1512  if (!maybe_values->To(&values)) return maybe_values;
1513  }
1514  set_properties(values);
1515  }
1516  set_map(new_map);
1517  return FastPropertyAtPut(field_index, value);
1518 }
1519 
1520 
1521 static bool IsIdentifier(UnicodeCache* cache,
1522  unibrow::CharacterStream* buffer) {
1523  // Checks whether the buffer contains an identifier (no escape).
1524  if (!buffer->has_more()) return false;
1525  if (!cache->IsIdentifierStart(buffer->GetNext())) {
1526  return false;
1527  }
1528  while (buffer->has_more()) {
1529  if (!cache->IsIdentifierPart(buffer->GetNext())) {
1530  return false;
1531  }
1532  }
1533  return true;
1534 }
1535 
1536 
1538  Object* value,
1539  PropertyAttributes attributes,
1540  StoreFromKeyed store_mode) {
1541  ASSERT(!IsJSGlobalProxy());
1543  map()->instance_descriptors()->Search(
1544  name, map()->NumberOfOwnDescriptors()));
1545 
1546  // Normalize the object if the name is an actual string (not the
1547  // hidden symbols) and is not a real identifier.
1548  // Normalize the object if it will have too many fast properties.
1549  Isolate* isolate = GetHeap()->isolate();
1550  StringInputBuffer buffer(name);
1551  if ((!IsIdentifier(isolate->unicode_cache(), &buffer)
1552  && name != isolate->heap()->hidden_symbol()) ||
1553  (map()->unused_property_fields() == 0 &&
1554  TooManyFastProperties(properties()->length(), store_mode))) {
1555  Object* obj;
1556  MaybeObject* maybe_obj =
1558  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1559 
1560  return AddSlowProperty(name, value, attributes);
1561  }
1562 
1563  // Compute the new index for new field.
1564  int index = map()->NextFreePropertyIndex();
1565 
1566  // Allocate new instance descriptors with (name, index) added
1567  FieldDescriptor new_field(name, index, attributes, 0);
1568 
1569  ASSERT(index < map()->inobject_properties() ||
1570  (index - map()->inobject_properties()) < properties()->length() ||
1571  map()->unused_property_fields() == 0);
1572 
1573  FixedArray* values = NULL;
1574 
1575  if (map()->unused_property_fields() == 0) {
1576  // Make room for the new value
1577  MaybeObject* maybe_values =
1578  properties()->CopySize(properties()->length() + kFieldsAdded);
1579  if (!maybe_values->To(&values)) return maybe_values;
1580  }
1581 
1582  // Only allow map transition if the object isn't the global object.
1583  TransitionFlag flag = isolate->empty_object_map() != map()
1585  : OMIT_TRANSITION;
1586 
1587  Map* new_map;
1588  MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag);
1589  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1590 
1591  if (map()->unused_property_fields() == 0) {
1592  ASSERT(values != NULL);
1593  set_properties(values);
1595  } else {
1596  new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
1597  }
1598 
1599  set_map(new_map);
1600  return FastPropertyAtPut(index, value);
1601 }
1602 
1603 
1605  String* name,
1606  JSFunction* function,
1607  PropertyAttributes attributes) {
1608  // Allocate new instance descriptors with (name, function) added
1609  ConstantFunctionDescriptor d(name, function, attributes, 0);
1610 
1611  Heap* heap = GetHeap();
1613  // Do not add transitions to the empty object map (map of "new Object()"),
1614  // nor to global objects.
1615  (map() == heap->isolate()->empty_object_map() || IsGlobalObject() ||
1616  // Don't add transitions to special properties with non-trivial
1617  // attributes.
1618  // TODO(verwaest): Once we support attribute changes, these transitions
1619  // should be kept as well.
1620  attributes != NONE)
1621  ? OMIT_TRANSITION
1623 
1624  Map* new_map;
1625  MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag);
1626  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1627 
1628  set_map(new_map);
1629  return function;
1630 }
1631 
1632 
1633 // Add property in slow mode
1635  Object* value,
1636  PropertyAttributes attributes) {
1639  Object* store_value = value;
1640  if (IsGlobalObject()) {
1641  // In case name is an orphaned property reuse the cell.
1642  int entry = dict->FindEntry(name);
1643  if (entry != StringDictionary::kNotFound) {
1644  store_value = dict->ValueAt(entry);
1645  JSGlobalPropertyCell::cast(store_value)->set_value(value);
1646  // Assign an enumeration index to the property and update
1647  // SetNextEnumerationIndex.
1648  int index = dict->NextEnumerationIndex();
1649  PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
1650  dict->SetNextEnumerationIndex(index + 1);
1651  dict->SetEntry(entry, name, store_value, details);
1652  return value;
1653  }
1654  Heap* heap = GetHeap();
1655  { MaybeObject* maybe_store_value =
1656  heap->AllocateJSGlobalPropertyCell(value);
1657  if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
1658  }
1659  JSGlobalPropertyCell::cast(store_value)->set_value(value);
1660  }
1661  PropertyDetails details = PropertyDetails(attributes, NORMAL);
1662  Object* result;
1663  { MaybeObject* maybe_result = dict->Add(name, store_value, details);
1664  if (!maybe_result->ToObject(&result)) return maybe_result;
1665  }
1666  if (dict != result) set_properties(StringDictionary::cast(result));
1667  return value;
1668 }
1669 
1670 
1671 MaybeObject* JSObject::AddProperty(String* name,
1672  Object* value,
1673  PropertyAttributes attributes,
1674  StrictModeFlag strict_mode,
1675  JSReceiver::StoreFromKeyed store_mode,
1676  ExtensibilityCheck extensibility_check) {
1677  ASSERT(!IsJSGlobalProxy());
1678  Map* map_of_this = map();
1679  Heap* heap = GetHeap();
1680  if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK &&
1681  !map_of_this->is_extensible()) {
1682  if (strict_mode == kNonStrictMode) {
1683  return value;
1684  } else {
1685  Handle<Object> args[1] = {Handle<String>(name)};
1686  return heap->isolate()->Throw(
1687  *FACTORY->NewTypeError("object_not_extensible",
1688  HandleVector(args, 1)));
1689  }
1690  }
1691  if (HasFastProperties()) {
1692  // Ensure the descriptor array does not get too big.
1693  if (map_of_this->NumberOfOwnDescriptors() <
1695  if (value->IsJSFunction()) {
1696  return AddConstantFunctionProperty(name,
1697  JSFunction::cast(value),
1698  attributes);
1699  } else {
1700  return AddFastProperty(name, value, attributes, store_mode);
1701  }
1702  } else {
1703  // Normalize the object to prevent very large instance descriptors.
1704  // This eliminates unwanted N^2 allocation and lookup behavior.
1705  Object* obj;
1706  { MaybeObject* maybe_obj =
1708  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1709  }
1710  }
1711  }
1712  return AddSlowProperty(name, value, attributes);
1713 }
1714 
1715 
1717  String* name,
1718  Object* value,
1719  PropertyAttributes attributes,
1720  StrictModeFlag strict_mode,
1721  ExtensibilityCheck extensibility_check) {
1722  // Check local property, ignore interceptor.
1723  LookupResult result(GetIsolate());
1724  LocalLookupRealNamedProperty(name, &result);
1725  if (!result.IsFound()) map()->LookupTransition(this, name, &result);
1726  if (result.IsFound()) {
1727  // An existing property or a map transition was found. Use set property to
1728  // handle all these cases.
1729  return SetProperty(&result, name, value, attributes, strict_mode);
1730  }
1731  bool done = false;
1732  MaybeObject* result_object;
1733  result_object =
1734  SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done);
1735  if (done) return result_object;
1736  // Add a new real property.
1737  return AddProperty(name, value, attributes, strict_mode,
1738  MAY_BE_STORE_FROM_KEYED, extensibility_check);
1739 }
1740 
1741 
1743  Object* value,
1744  PropertyAttributes attributes) {
1745  StringDictionary* dictionary = property_dictionary();
1746  int old_index = dictionary->FindEntry(name);
1747  int new_enumeration_index = 0; // 0 means "Use the next available index."
1748  if (old_index != -1) {
1749  // All calls to ReplaceSlowProperty have had all transitions removed.
1750  new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index();
1751  }
1752 
1753  PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
1754  return SetNormalizedProperty(name, value, new_details);
1755 }
1756 
1757 
1759  int transition_index,
1760  String* name,
1761  Object* new_value,
1762  PropertyAttributes attributes) {
1763  Map* old_map = map();
1764  Map* old_target = old_map->GetTransition(transition_index);
1765  Object* result;
1766 
1767  MaybeObject* maybe_result =
1768  ConvertDescriptorToField(name, new_value, attributes);
1769  if (!maybe_result->To(&result)) return maybe_result;
1770 
1771  if (!HasFastProperties()) return result;
1772 
1773  // This method should only be used to convert existing transitions. Objects
1774  // with the map of "new Object()" cannot have transitions in the first place.
1775  Map* new_map = map();
1776  ASSERT(new_map != GetIsolate()->empty_object_map());
1777 
1778  // TODO(verwaest): From here on we lose existing map transitions, causing
1779  // invalid back pointers. This will change once we can store multiple
1780  // transitions with the same key.
1781 
1782  bool owned_descriptors = old_map->owns_descriptors();
1783  if (owned_descriptors ||
1784  old_target->instance_descriptors() == old_map->instance_descriptors()) {
1785  // Since the conversion above generated a new fast map with an additional
1786  // property which can be shared as well, install this descriptor pointer
1787  // along the entire chain of smaller maps.
1788  Map* map;
1789  DescriptorArray* new_descriptors = new_map->instance_descriptors();
1790  DescriptorArray* old_descriptors = old_map->instance_descriptors();
1791  for (Object* current = old_map;
1792  !current->IsUndefined();
1793  current = map->GetBackPointer()) {
1794  map = Map::cast(current);
1795  if (map->instance_descriptors() != old_descriptors) break;
1797  map->set_instance_descriptors(new_descriptors);
1798  }
1799  old_map->set_owns_descriptors(false);
1800  }
1801 
1802  old_map->SetTransition(transition_index, new_map);
1803  new_map->SetBackPointer(old_map);
1804  return result;
1805 }
1806 
1807 
1809  Object* new_value,
1810  PropertyAttributes attributes) {
1811  if (map()->unused_property_fields() == 0 &&
1812  TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) {
1813  Object* obj;
1814  MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1815  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1816  return ReplaceSlowProperty(name, new_value, attributes);
1817  }
1818 
1819  int index = map()->NextFreePropertyIndex();
1820  FieldDescriptor new_field(name, index, attributes, 0);
1821 
1822  // Make a new map for the object.
1823  Map* new_map;
1824  MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field,
1825  OMIT_TRANSITION);
1826  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1827 
1828  // Make new properties array if necessary.
1829  FixedArray* new_properties = NULL;
1830  int new_unused_property_fields = map()->unused_property_fields() - 1;
1831  if (map()->unused_property_fields() == 0) {
1832  new_unused_property_fields = kFieldsAdded - 1;
1833  MaybeObject* maybe_new_properties =
1834  properties()->CopySize(properties()->length() + kFieldsAdded);
1835  if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties;
1836  }
1837 
1838  // Update pointers to commit changes.
1839  // Object points to the new map.
1840  new_map->set_unused_property_fields(new_unused_property_fields);
1841  set_map(new_map);
1842  if (new_properties != NULL) {
1843  set_properties(new_properties);
1844  }
1845  return FastPropertyAtPut(index, new_value);
1846 }
1847 
1848 
1849 
1851  String* name,
1852  Object* value,
1853  PropertyAttributes attributes,
1854  StrictModeFlag strict_mode) {
1855  Isolate* isolate = GetIsolate();
1856  HandleScope scope(isolate);
1857  Handle<JSObject> this_handle(this);
1858  Handle<String> name_handle(name);
1859  Handle<Object> value_handle(value, isolate);
1861  if (!interceptor->setter()->IsUndefined()) {
1862  LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name));
1863  CustomArguments args(isolate, interceptor->data(), this, this);
1864  v8::AccessorInfo info(args.end());
1865  v8::NamedPropertySetter setter =
1866  v8::ToCData<v8::NamedPropertySetter>(interceptor->setter());
1867  v8::Handle<v8::Value> result;
1868  {
1869  // Leaving JavaScript.
1870  VMState state(isolate, EXTERNAL);
1871  Handle<Object> value_unhole(value->IsTheHole() ?
1872  isolate->heap()->undefined_value() :
1873  value,
1874  isolate);
1875  result = setter(v8::Utils::ToLocal(name_handle),
1876  v8::Utils::ToLocal(value_unhole),
1877  info);
1878  }
1880  if (!result.IsEmpty()) return *value_handle;
1881  }
1882  MaybeObject* raw_result =
1883  this_handle->SetPropertyPostInterceptor(*name_handle,
1884  *value_handle,
1885  attributes,
1886  strict_mode,
1889  return raw_result;
1890 }
1891 
1892 
1894  Handle<String> key,
1895  Handle<Object> value,
1896  PropertyAttributes attributes,
1897  StrictModeFlag strict_mode) {
1898  CALL_HEAP_FUNCTION(object->GetIsolate(),
1899  object->SetProperty(*key, *value, attributes, strict_mode),
1900  Object);
1901 }
1902 
1903 
1904 MaybeObject* JSReceiver::SetProperty(String* name,
1905  Object* value,
1906  PropertyAttributes attributes,
1907  StrictModeFlag strict_mode,
1908  JSReceiver::StoreFromKeyed store_mode) {
1909  LookupResult result(GetIsolate());
1910  LocalLookup(name, &result);
1911  if (!result.IsFound()) {
1912  map()->LookupTransition(JSObject::cast(this), name, &result);
1913  }
1914  return SetProperty(&result, name, value, attributes, strict_mode, store_mode);
1915 }
1916 
1917 
1919  String* name,
1920  Object* value,
1921  JSObject* holder,
1922  StrictModeFlag strict_mode) {
1923  Isolate* isolate = GetIsolate();
1924  HandleScope scope(isolate);
1925 
1926  // We should never get here to initialize a const with the hole
1927  // value since a const declaration would conflict with the setter.
1928  ASSERT(!value->IsTheHole());
1929  Handle<Object> value_handle(value, isolate);
1930 
1931  // To accommodate both the old and the new api we switch on the
1932  // data structure used to store the callbacks. Eventually foreign
1933  // callbacks should be phased out.
1934  if (structure->IsForeign()) {
1935  AccessorDescriptor* callback =
1936  reinterpret_cast<AccessorDescriptor*>(
1937  Foreign::cast(structure)->foreign_address());
1938  MaybeObject* obj = (callback->setter)(this, value, callback->data);
1940  if (obj->IsFailure()) return obj;
1941  return *value_handle;
1942  }
1943 
1944  if (structure->IsAccessorInfo()) {
1945  // api style callbacks
1946  AccessorInfo* data = AccessorInfo::cast(structure);
1947  if (!data->IsCompatibleReceiver(this)) {
1948  Handle<Object> name_handle(name);
1949  Handle<Object> receiver_handle(this);
1950  Handle<Object> args[2] = { name_handle, receiver_handle };
1951  Handle<Object> error =
1952  isolate->factory()->NewTypeError("incompatible_method_receiver",
1953  HandleVector(args,
1954  ARRAY_SIZE(args)));
1955  return isolate->Throw(*error);
1956  }
1957  Object* call_obj = data->setter();
1958  v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
1959  if (call_fun == NULL) return value;
1960  Handle<String> key(name);
1961  LOG(isolate, ApiNamedPropertyAccess("store", this, name));
1962  CustomArguments args(isolate, data->data(), this, JSObject::cast(holder));
1963  v8::AccessorInfo info(args.end());
1964  {
1965  // Leaving JavaScript.
1966  VMState state(isolate, EXTERNAL);
1967  call_fun(v8::Utils::ToLocal(key),
1968  v8::Utils::ToLocal(value_handle),
1969  info);
1970  }
1972  return *value_handle;
1973  }
1974 
1975  if (structure->IsAccessorPair()) {
1976  Object* setter = AccessorPair::cast(structure)->setter();
1977  if (setter->IsSpecFunction()) {
1978  // TODO(rossberg): nicer would be to cast to some JSCallable here...
1979  return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
1980  } else {
1981  if (strict_mode == kNonStrictMode) {
1982  return value;
1983  }
1984  Handle<String> key(name);
1985  Handle<Object> holder_handle(holder, isolate);
1986  Handle<Object> args[2] = { key, holder_handle };
1987  return isolate->Throw(
1988  *isolate->factory()->NewTypeError("no_setter_in_callback",
1989  HandleVector(args, 2)));
1990  }
1991  }
1992 
1993  UNREACHABLE();
1994  return NULL;
1995 }
1996 
1997 
1999  Object* value) {
2000  Isolate* isolate = GetIsolate();
2001  Handle<Object> value_handle(value, isolate);
2002  Handle<JSReceiver> fun(setter, isolate);
2003  Handle<JSReceiver> self(this, isolate);
2004 #ifdef ENABLE_DEBUGGER_SUPPORT
2005  Debug* debug = isolate->debug();
2006  // Handle stepping into a setter if step into is active.
2007  // TODO(rossberg): should this apply to getters that are function proxies?
2008  if (debug->StepInActive() && fun->IsJSFunction()) {
2009  debug->HandleStepIn(
2011  }
2012 #endif
2013  bool has_pending_exception;
2014  Handle<Object> argv[] = { value_handle };
2015  Execution::Call(fun, self, ARRAY_SIZE(argv), argv, &has_pending_exception);
2016  // Check for pending exception and return the result.
2017  if (has_pending_exception) return Failure::Exception();
2018  return *value_handle;
2019 }
2020 
2021 
2023  uint32_t index,
2024  Object* value,
2025  bool* found,
2026  StrictModeFlag strict_mode) {
2027  Heap* heap = GetHeap();
2028  for (Object* pt = GetPrototype();
2029  pt != heap->null_value();
2030  pt = pt->GetPrototype()) {
2031  if (pt->IsJSProxy()) {
2032  String* name;
2033  MaybeObject* maybe = GetHeap()->Uint32ToString(index);
2034  if (!maybe->To<String>(&name)) {
2035  *found = true; // Force abort
2036  return maybe;
2037  }
2039  this, name, value, NONE, strict_mode, found);
2040  }
2041  if (!JSObject::cast(pt)->HasDictionaryElements()) {
2042  continue;
2043  }
2044  SeededNumberDictionary* dictionary =
2046  int entry = dictionary->FindEntry(index);
2047  if (entry != SeededNumberDictionary::kNotFound) {
2048  PropertyDetails details = dictionary->DetailsAt(entry);
2049  if (details.type() == CALLBACKS) {
2050  *found = true;
2051  return SetElementWithCallback(dictionary->ValueAt(entry),
2052  index,
2053  value,
2054  JSObject::cast(pt),
2055  strict_mode);
2056  }
2057  }
2058  }
2059  *found = false;
2060  return heap->the_hole_value();
2061 }
2062 
2063 MaybeObject* JSObject::SetPropertyViaPrototypes(
2064  String* name,
2065  Object* value,
2066  PropertyAttributes attributes,
2067  StrictModeFlag strict_mode,
2068  bool* done) {
2069  Heap* heap = GetHeap();
2070  Isolate* isolate = heap->isolate();
2071 
2072  *done = false;
2073  // We could not find a local property so let's check whether there is an
2074  // accessor that wants to handle the property, or whether the property is
2075  // read-only on the prototype chain.
2076  LookupResult result(isolate);
2077  LookupRealNamedPropertyInPrototypes(name, &result);
2078  if (result.IsFound()) {
2079  switch (result.type()) {
2080  case NORMAL:
2081  case FIELD:
2082  case CONSTANT_FUNCTION:
2083  *done = result.IsReadOnly();
2084  break;
2085  case INTERCEPTOR: {
2086  PropertyAttributes attr =
2087  result.holder()->GetPropertyAttributeWithInterceptor(
2088  this, name, true);
2089  *done = !!(attr & READ_ONLY);
2090  break;
2091  }
2092  case CALLBACKS: {
2093  if (!FLAG_es5_readonly && result.IsReadOnly()) break;
2094  *done = true;
2095  return SetPropertyWithCallback(result.GetCallbackObject(),
2096  name, value, result.holder(), strict_mode);
2097  }
2098  case HANDLER: {
2099  return result.proxy()->SetPropertyViaPrototypesWithHandler(
2100  this, name, value, attributes, strict_mode, done);
2101  }
2102  case TRANSITION:
2103  case NONEXISTENT:
2104  UNREACHABLE();
2105  break;
2106  }
2107  }
2108 
2109  // If we get here with *done true, we have encountered a read-only property.
2110  if (!FLAG_es5_readonly) *done = false;
2111  if (*done) {
2112  if (strict_mode == kNonStrictMode) return value;
2113  Handle<Object> args[] = { Handle<Object>(name), Handle<Object>(this)};
2114  return isolate->Throw(*isolate->factory()->NewTypeError(
2115  "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2116  }
2117  return heap->the_hole_value();
2118 }
2119 
2120 
2122 
2123 
2124 static void ZapEndOfFixedArray(Address new_end, int to_trim) {
2125  // If we are doing a big trim in old space then we zap the space.
2126  Object** zap = reinterpret_cast<Object**>(new_end);
2127  zap++; // Header of filler must be at least one word so skip that.
2128  for (int i = 1; i < to_trim; i++) {
2129  *zap++ = Smi::FromInt(0);
2130  }
2131 }
2132 
2133 
2134 template<RightTrimMode trim_mode>
2135 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
2136  ASSERT(elms->map() != HEAP->fixed_cow_array_map());
2137  // For now this trick is only applied to fixed arrays in new and paged space.
2138  ASSERT(!HEAP->lo_space()->Contains(elms));
2139 
2140  const int len = elms->length();
2141 
2142  ASSERT(to_trim < len);
2143 
2144  Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim);
2145 
2146  if (trim_mode != FROM_GC || Heap::ShouldZapGarbage()) {
2147  ZapEndOfFixedArray(new_end, to_trim);
2148  }
2149 
2150  int size_delta = to_trim * kPointerSize;
2151 
2152  // Technically in new space this write might be omitted (except for
2153  // debug mode which iterates through the heap), but to play safer
2154  // we still do it.
2155  heap->CreateFillerObjectAt(new_end, size_delta);
2156 
2157  elms->set_length(len - to_trim);
2158 
2159  // Maintain marking consistency for IncrementalMarking.
2161  if (trim_mode == FROM_GC) {
2162  MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta);
2163  } else {
2164  MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta);
2165  }
2166  }
2167 }
2168 
2169 
2171  Handle<DescriptorArray> descriptors(map->instance_descriptors());
2172  if (slack <= descriptors->NumberOfSlackDescriptors()) return;
2173  int number_of_descriptors = descriptors->number_of_descriptors();
2174  Isolate* isolate = map->GetIsolate();
2175  Handle<DescriptorArray> new_descriptors =
2176  isolate->factory()->NewDescriptorArray(number_of_descriptors, slack);
2177  DescriptorArray::WhitenessWitness witness(*new_descriptors);
2178 
2179  for (int i = 0; i < number_of_descriptors; ++i) {
2180  new_descriptors->CopyFrom(i, *descriptors, i, witness);
2181  }
2182 
2183  map->set_instance_descriptors(*new_descriptors);
2184 }
2185 
2186 
2188  Handle<Object> descriptors) {
2189  Isolate* isolate = map->GetIsolate();
2190  Handle<DescriptorArray> array(map->instance_descriptors());
2191  NeanderArray callbacks(descriptors);
2192  int nof_callbacks = callbacks.length();
2193 
2194  ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks);
2195 
2196  // Ensure the keys are symbols before writing them into the instance
2197  // descriptor. Since it may cause a GC, it has to be done before we
2198  // temporarily put the heap in an invalid state while appending descriptors.
2199  for (int i = 0; i < nof_callbacks; ++i) {
2200  Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
2201  Handle<String> key =
2202  isolate->factory()->SymbolFromString(
2203  Handle<String>(String::cast(entry->name())));
2204  entry->set_name(*key);
2205  }
2206 
2207  int nof = map->NumberOfOwnDescriptors();
2208 
2209  // Fill in new callback descriptors. Process the callbacks from
2210  // back to front so that the last callback with a given name takes
2211  // precedence over previously added callbacks with that name.
2212  for (int i = nof_callbacks - 1; i >= 0; i--) {
2213  AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
2214  String* key = String::cast(entry->name());
2215  // Check if a descriptor with this name already exists before writing.
2216  if (array->Search(key, nof) == DescriptorArray::kNotFound) {
2217  CallbacksDescriptor desc(key, entry, entry->property_attributes());
2218  array->Append(&desc);
2219  nof += 1;
2220  }
2221  }
2222 
2223  map->SetNumberOfOwnDescriptors(nof);
2224 }
2225 
2226 
2227 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
2228  ASSERT(!map.is_null());
2229  for (int i = 0; i < maps->length(); ++i) {
2230  if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
2231  }
2232  return false;
2233 }
2234 
2235 
2236 template <class T>
2237 static Handle<T> MaybeNull(T* p) {
2238  if (p == NULL) return Handle<T>::null();
2239  return Handle<T>(p);
2240 }
2241 
2242 
2244  ElementsKind kind = elements_kind();
2245  Handle<Map> transitioned_map = Handle<Map>::null();
2246  Handle<Map> current_map(this);
2247  bool packed = IsFastPackedElementsKind(kind);
2249  while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
2250  kind = GetNextMoreGeneralFastElementsKind(kind, false);
2251  Handle<Map> maybe_transitioned_map =
2252  MaybeNull(current_map->LookupElementsTransitionMap(kind));
2253  if (maybe_transitioned_map.is_null()) break;
2254  if (ContainsMap(candidates, maybe_transitioned_map) &&
2255  (packed || !IsFastPackedElementsKind(kind))) {
2256  transitioned_map = maybe_transitioned_map;
2257  if (!IsFastPackedElementsKind(kind)) packed = false;
2258  }
2259  current_map = maybe_transitioned_map;
2260  }
2261  }
2262  return transitioned_map;
2263 }
2264 
2265 
2266 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
2267  Map* current_map = map;
2269  int to_index = IsFastElementsKind(to_kind)
2272 
2273  ASSERT(index <= to_index);
2274 
2275  for (; index < to_index; ++index) {
2276  if (!current_map->HasElementsTransition()) return current_map;
2277  current_map = current_map->elements_transition_map();
2278  }
2279  if (!IsFastElementsKind(to_kind) && current_map->HasElementsTransition()) {
2280  Map* next_map = current_map->elements_transition_map();
2281  if (next_map->elements_kind() == to_kind) return next_map;
2282  }
2283  ASSERT(IsFastElementsKind(to_kind)
2284  ? current_map->elements_kind() == to_kind
2285  : current_map->elements_kind() == TERMINAL_FAST_ELEMENTS_KIND);
2286  return current_map;
2287 }
2288 
2289 
2291  Map* to_map = FindClosestElementsTransition(this, to_kind);
2292  if (to_map->elements_kind() == to_kind) return to_map;
2293  return NULL;
2294 }
2295 
2296 
2297 static MaybeObject* AddMissingElementsTransitions(Map* map,
2298  ElementsKind to_kind) {
2301  int to_index = IsFastElementsKind(to_kind)
2304 
2305  ASSERT(index <= to_index);
2306 
2307  Map* current_map = map;
2308 
2309  for (; index < to_index; ++index) {
2310  ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index + 1);
2311  MaybeObject* maybe_next_map =
2312  current_map->CopyAsElementsKind(next_kind, INSERT_TRANSITION);
2313  if (!maybe_next_map->To(&current_map)) return maybe_next_map;
2314  }
2315 
2316  // In case we are exiting the fast elements kind system, just add the map in
2317  // the end.
2318  if (!IsFastElementsKind(to_kind)) {
2319  MaybeObject* maybe_next_map =
2320  current_map->CopyAsElementsKind(to_kind, INSERT_TRANSITION);
2321  if (!maybe_next_map->To(&current_map)) return maybe_next_map;
2322  }
2323 
2324  ASSERT(current_map->elements_kind() == to_kind);
2325  return current_map;
2326 }
2327 
2328 
2330  ElementsKind to_kind) {
2331  Isolate* isolate = object->GetIsolate();
2332  CALL_HEAP_FUNCTION(isolate,
2333  object->GetElementsTransitionMap(isolate, to_kind),
2334  Map);
2335 }
2336 
2337 
2339  Map* start_map = map();
2340  ElementsKind from_kind = start_map->elements_kind();
2341 
2342  if (from_kind == to_kind) {
2343  return start_map;
2344  }
2345 
2346  bool allow_store_transition =
2347  // Only remember the map transition if the object's map is NOT equal to
2348  // the global object_function's map and there is not an already existing
2349  // non-matching element transition.
2350  (GetIsolate()->empty_object_map() != map()) &&
2351  !start_map->IsUndefined() && !start_map->is_shared() &&
2352  IsFastElementsKind(from_kind);
2353 
2354  // Only store fast element maps in ascending generality.
2355  if (IsFastElementsKind(to_kind)) {
2356  allow_store_transition &=
2357  IsTransitionableFastElementsKind(from_kind) &&
2358  IsMoreGeneralElementsKindTransition(from_kind, to_kind);
2359  }
2360 
2361  if (!allow_store_transition) {
2362  return start_map->CopyAsElementsKind(to_kind, OMIT_TRANSITION);
2363  }
2364 
2365  Map* closest_map = FindClosestElementsTransition(start_map, to_kind);
2366 
2367  if (closest_map->elements_kind() == to_kind) {
2368  return closest_map;
2369  }
2370 
2371  return AddMissingElementsTransitions(closest_map, to_kind);
2372 }
2373 
2374 
2376  LookupResult* result) {
2377  if (IsJSGlobalProxy()) {
2378  Object* proto = GetPrototype();
2379  if (proto->IsNull()) return result->NotFound();
2380  ASSERT(proto->IsJSGlobalObject());
2381  // A GlobalProxy's prototype should always be a proper JSObject.
2382  return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
2383  }
2384 
2385  if (HasFastProperties()) {
2386  map()->LookupDescriptor(this, name, result);
2387  // A property or a map transition was found. We return all of these result
2388  // types because LocalLookupRealNamedProperty is used when setting
2389  // properties where map transitions are handled.
2390  ASSERT(!result->IsFound() ||
2391  (result->holder() == this && result->IsFastPropertyType()));
2392  // Disallow caching for uninitialized constants. These can only
2393  // occur as fields.
2394  if (result->IsField() &&
2395  result->IsReadOnly() &&
2396  FastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
2397  result->DisallowCaching();
2398  }
2399  return;
2400  }
2401 
2402  int entry = property_dictionary()->FindEntry(name);
2403  if (entry != StringDictionary::kNotFound) {
2404  Object* value = property_dictionary()->ValueAt(entry);
2405  if (IsGlobalObject()) {
2406  PropertyDetails d = property_dictionary()->DetailsAt(entry);
2407  if (d.IsDeleted()) {
2408  result->NotFound();
2409  return;
2410  }
2411  value = JSGlobalPropertyCell::cast(value)->value();
2412  }
2413  // Make sure to disallow caching for uninitialized constants
2414  // found in the dictionary-mode objects.
2415  if (value->IsTheHole()) result->DisallowCaching();
2416  result->DictionaryResult(this, entry);
2417  return;
2418  }
2419 
2420  result->NotFound();
2421 }
2422 
2423 
2424 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
2425  LocalLookupRealNamedProperty(name, result);
2426  if (result->IsFound()) return;
2427 
2429 }
2430 
2431 
2433  LookupResult* result) {
2434  Heap* heap = GetHeap();
2435  for (Object* pt = GetPrototype();
2436  pt != heap->null_value();
2437  pt = pt->GetPrototype()) {
2438  if (pt->IsJSProxy()) {
2439  return result->HandlerResult(JSProxy::cast(pt));
2440  }
2441  JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
2442  ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR));
2443  if (result->IsFound()) return;
2444  }
2445  result->NotFound();
2446 }
2447 
2448 
2449 // We only need to deal with CALLBACKS and INTERCEPTORS
2451  LookupResult* result,
2452  String* name,
2453  Object* value,
2454  bool check_prototype,
2455  StrictModeFlag strict_mode) {
2456  if (check_prototype && !result->IsProperty()) {
2458  }
2459 
2460  if (result->IsProperty()) {
2461  if (!result->IsReadOnly()) {
2462  switch (result->type()) {
2463  case CALLBACKS: {
2464  Object* obj = result->GetCallbackObject();
2465  if (obj->IsAccessorInfo()) {
2466  AccessorInfo* info = AccessorInfo::cast(obj);
2467  if (info->all_can_write()) {
2468  return SetPropertyWithCallback(result->GetCallbackObject(),
2469  name,
2470  value,
2471  result->holder(),
2472  strict_mode);
2473  }
2474  }
2475  break;
2476  }
2477  case INTERCEPTOR: {
2478  // Try lookup real named properties. Note that only property can be
2479  // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
2480  LookupResult r(GetIsolate());
2481  LookupRealNamedProperty(name, &r);
2482  if (r.IsProperty()) {
2484  name,
2485  value,
2486  check_prototype,
2487  strict_mode);
2488  }
2489  break;
2490  }
2491  default: {
2492  break;
2493  }
2494  }
2495  }
2496  }
2497 
2498  Isolate* isolate = GetIsolate();
2499  HandleScope scope(isolate);
2500  Handle<Object> value_handle(value);
2501  isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
2502  return *value_handle;
2503 }
2504 
2505 
2506 MaybeObject* JSReceiver::SetProperty(LookupResult* result,
2507  String* key,
2508  Object* value,
2509  PropertyAttributes attributes,
2510  StrictModeFlag strict_mode,
2511  JSReceiver::StoreFromKeyed store_mode) {
2512  if (result->IsHandler()) {
2513  return result->proxy()->SetPropertyWithHandler(
2514  this, key, value, attributes, strict_mode);
2515  } else {
2516  return JSObject::cast(this)->SetPropertyForResult(
2517  result, key, value, attributes, strict_mode, store_mode);
2518  }
2519 }
2520 
2521 
2523  Isolate* isolate = GetIsolate();
2524  HandleScope scope(isolate);
2525  Handle<Object> receiver(this);
2526  Handle<Object> name(name_raw);
2527 
2528  Handle<Object> args[] = { name };
2529  Handle<Object> result = CallTrap(
2530  "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
2531  if (isolate->has_pending_exception()) return false;
2532 
2533  return result->ToBoolean()->IsTrue();
2534 }
2535 
2536 
2538  JSReceiver* receiver_raw,
2539  String* name_raw,
2540  Object* value_raw,
2541  PropertyAttributes attributes,
2542  StrictModeFlag strict_mode) {
2543  Isolate* isolate = GetIsolate();
2544  HandleScope scope(isolate);
2545  Handle<JSReceiver> receiver(receiver_raw);
2546  Handle<Object> name(name_raw);
2547  Handle<Object> value(value_raw);
2548 
2549  Handle<Object> args[] = { receiver, name, value };
2550  CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
2551  if (isolate->has_pending_exception()) return Failure::Exception();
2552 
2553  return *value;
2554 }
2555 
2556 
2558  JSReceiver* receiver_raw,
2559  String* name_raw,
2560  Object* value_raw,
2561  PropertyAttributes attributes,
2562  StrictModeFlag strict_mode,
2563  bool* done) {
2564  Isolate* isolate = GetIsolate();
2565  Handle<JSProxy> proxy(this);
2566  Handle<JSReceiver> receiver(receiver_raw);
2567  Handle<String> name(name_raw);
2568  Handle<Object> value(value_raw);
2569  Handle<Object> handler(this->handler()); // Trap might morph proxy.
2570 
2571  *done = true; // except where redefined...
2572  Handle<Object> args[] = { name };
2573  Handle<Object> result = proxy->CallTrap(
2574  "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2575  if (isolate->has_pending_exception()) return Failure::Exception();
2576 
2577  if (result->IsUndefined()) {
2578  *done = false;
2579  return GetHeap()->the_hole_value();
2580  }
2581 
2582  // Emulate [[GetProperty]] semantics for proxies.
2583  bool has_pending_exception;
2584  Handle<Object> argv[] = { result };
2585  Handle<Object> desc =
2586  Execution::Call(isolate->to_complete_property_descriptor(), result,
2587  ARRAY_SIZE(argv), argv, &has_pending_exception);
2588  if (has_pending_exception) return Failure::Exception();
2589 
2590  // [[GetProperty]] requires to check that all properties are configurable.
2591  Handle<String> configurable_name =
2592  isolate->factory()->LookupAsciiSymbol("configurable_");
2593  Handle<Object> configurable(
2594  v8::internal::GetProperty(desc, configurable_name));
2595  ASSERT(!isolate->has_pending_exception());
2596  ASSERT(configurable->IsTrue() || configurable->IsFalse());
2597  if (configurable->IsFalse()) {
2598  Handle<String> trap =
2599  isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
2600  Handle<Object> args[] = { handler, trap, name };
2601  Handle<Object> error = isolate->factory()->NewTypeError(
2602  "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2603  return isolate->Throw(*error);
2604  }
2605  ASSERT(configurable->IsTrue());
2606 
2607  // Check for DataDescriptor.
2608  Handle<String> hasWritable_name =
2609  isolate->factory()->LookupAsciiSymbol("hasWritable_");
2610  Handle<Object> hasWritable(v8::internal::GetProperty(desc, hasWritable_name));
2611  ASSERT(!isolate->has_pending_exception());
2612  ASSERT(hasWritable->IsTrue() || hasWritable->IsFalse());
2613  if (hasWritable->IsTrue()) {
2614  Handle<String> writable_name =
2615  isolate->factory()->LookupAsciiSymbol("writable_");
2616  Handle<Object> writable(v8::internal::GetProperty(desc, writable_name));
2617  ASSERT(!isolate->has_pending_exception());
2618  ASSERT(writable->IsTrue() || writable->IsFalse());
2619  *done = writable->IsFalse();
2620  if (!*done) return GetHeap()->the_hole_value();
2621  if (strict_mode == kNonStrictMode) return *value;
2622  Handle<Object> args[] = { name, receiver };
2623  Handle<Object> error = isolate->factory()->NewTypeError(
2624  "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
2625  return isolate->Throw(*error);
2626  }
2627 
2628  // We have an AccessorDescriptor.
2629  Handle<String> set_name = isolate->factory()->LookupAsciiSymbol("set_");
2630  Handle<Object> setter(v8::internal::GetProperty(desc, set_name));
2631  ASSERT(!isolate->has_pending_exception());
2632  if (!setter->IsUndefined()) {
2633  // TODO(rossberg): nicer would be to cast to some JSCallable here...
2634  return receiver->SetPropertyWithDefinedSetter(
2635  JSReceiver::cast(*setter), *value);
2636  }
2637 
2638  if (strict_mode == kNonStrictMode) return *value;
2639  Handle<Object> args2[] = { name, proxy };
2640  Handle<Object> error = isolate->factory()->NewTypeError(
2641  "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2)));
2642  return isolate->Throw(*error);
2643 }
2644 
2645 
2647  String* name_raw, DeleteMode mode) {
2648  Isolate* isolate = GetIsolate();
2649  HandleScope scope(isolate);
2650  Handle<JSProxy> receiver(this);
2651  Handle<Object> name(name_raw);
2652 
2653  Handle<Object> args[] = { name };
2654  Handle<Object> result = CallTrap(
2655  "delete", Handle<Object>(), ARRAY_SIZE(args), args);
2656  if (isolate->has_pending_exception()) return Failure::Exception();
2657 
2658  Object* bool_result = result->ToBoolean();
2659  if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
2660  Handle<Object> handler(receiver->handler());
2661  Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete");
2662  Handle<Object> args[] = { handler, trap_name };
2663  Handle<Object> error = isolate->factory()->NewTypeError(
2664  "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
2665  isolate->Throw(*error);
2666  return Failure::Exception();
2667  }
2668  return bool_result;
2669 }
2670 
2671 
2673  uint32_t index,
2674  DeleteMode mode) {
2675  Isolate* isolate = GetIsolate();
2676  HandleScope scope(isolate);
2677  Handle<String> name = isolate->factory()->Uint32ToString(index);
2678  return JSProxy::DeletePropertyWithHandler(*name, mode);
2679 }
2680 
2681 
2683  JSReceiver* receiver_raw,
2684  String* name_raw) {
2685  Isolate* isolate = GetIsolate();
2686  HandleScope scope(isolate);
2687  Handle<JSProxy> proxy(this);
2688  Handle<Object> handler(this->handler()); // Trap might morph proxy.
2689  Handle<JSReceiver> receiver(receiver_raw);
2690  Handle<Object> name(name_raw);
2691 
2692  Handle<Object> args[] = { name };
2693  Handle<Object> result = CallTrap(
2694  "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2695  if (isolate->has_pending_exception()) return NONE;
2696 
2697  if (result->IsUndefined()) return ABSENT;
2698 
2699  bool has_pending_exception;
2700  Handle<Object> argv[] = { result };
2701  Handle<Object> desc =
2702  Execution::Call(isolate->to_complete_property_descriptor(), result,
2703  ARRAY_SIZE(argv), argv, &has_pending_exception);
2704  if (has_pending_exception) return NONE;
2705 
2706  // Convert result to PropertyAttributes.
2707  Handle<String> enum_n = isolate->factory()->LookupAsciiSymbol("enumerable");
2708  Handle<Object> enumerable(v8::internal::GetProperty(desc, enum_n));
2709  if (isolate->has_pending_exception()) return NONE;
2710  Handle<String> conf_n = isolate->factory()->LookupAsciiSymbol("configurable");
2711  Handle<Object> configurable(v8::internal::GetProperty(desc, conf_n));
2712  if (isolate->has_pending_exception()) return NONE;
2713  Handle<String> writ_n = isolate->factory()->LookupAsciiSymbol("writable");
2714  Handle<Object> writable(v8::internal::GetProperty(desc, writ_n));
2715  if (isolate->has_pending_exception()) return NONE;
2716 
2717  if (configurable->IsFalse()) {
2718  Handle<String> trap =
2719  isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
2720  Handle<Object> args[] = { handler, trap, name };
2721  Handle<Object> error = isolate->factory()->NewTypeError(
2722  "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2723  isolate->Throw(*error);
2724  return NONE;
2725  }
2726 
2727  int attributes = NONE;
2728  if (enumerable->ToBoolean()->IsFalse()) attributes |= DONT_ENUM;
2729  if (configurable->ToBoolean()->IsFalse()) attributes |= DONT_DELETE;
2730  if (writable->ToBoolean()->IsFalse()) attributes |= READ_ONLY;
2731  return static_cast<PropertyAttributes>(attributes);
2732 }
2733 
2734 
2736  JSReceiver* receiver,
2737  uint32_t index) {
2738  Isolate* isolate = GetIsolate();
2739  HandleScope scope(isolate);
2740  Handle<String> name = isolate->factory()->Uint32ToString(index);
2741  return GetPropertyAttributeWithHandler(receiver, *name);
2742 }
2743 
2744 
2746  Isolate* isolate = GetIsolate();
2747  HandleScope scope(isolate);
2748  Handle<JSProxy> self(this);
2749 
2750  // Save identity hash.
2751  MaybeObject* maybe_hash = GetIdentityHash(OMIT_CREATION);
2752 
2753  if (IsJSFunctionProxy()) {
2754  isolate->factory()->BecomeJSFunction(self);
2755  // Code will be set on the JavaScript side.
2756  } else {
2757  isolate->factory()->BecomeJSObject(self);
2758  }
2759  ASSERT(self->IsJSObject());
2760 
2761  // Inherit identity, if it was present.
2762  Object* hash;
2763  if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) {
2764  Handle<JSObject> new_self(JSObject::cast(*self));
2765  isolate->factory()->SetIdentityHash(new_self, Smi::cast(hash));
2766  }
2767 }
2768 
2769 
2771  Handle<Object> derived,
2772  int argc,
2773  Handle<Object> argv[]) {
2774  Isolate* isolate = GetIsolate();
2775  Handle<Object> handler(this->handler());
2776 
2777  Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol(name);
2778  Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2779  if (isolate->has_pending_exception()) return trap;
2780 
2781  if (trap->IsUndefined()) {
2782  if (derived.is_null()) {
2783  Handle<Object> args[] = { handler, trap_name };
2784  Handle<Object> error = isolate->factory()->NewTypeError(
2785  "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
2786  isolate->Throw(*error);
2787  return Handle<Object>();
2788  }
2789  trap = Handle<Object>(derived);
2790  }
2791 
2792  bool threw;
2793  return Execution::Call(trap, handler, argc, argv, &threw);
2794 }
2795 
2796 
2798  Handle<Map> map) {
2800  object->GetIsolate(),
2801  object->AddFastPropertyUsingMap(*map));
2802 }
2803 
2804 
2805 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
2806  String* name_raw,
2807  Object* value_raw,
2808  PropertyAttributes attributes,
2809  StrictModeFlag strict_mode,
2810  StoreFromKeyed store_mode) {
2811  Heap* heap = GetHeap();
2812  // Make sure that the top context does not change when doing callbacks or
2813  // interceptor calls.
2814  AssertNoContextChange ncc;
2815 
2816  // Optimization for 2-byte strings often used as keys in a decompression
2817  // dictionary. We make these short keys into symbols to avoid constantly
2818  // reallocating them.
2819  if (!name_raw->IsSymbol() && name_raw->length() <= 2) {
2820  Object* symbol_version;
2821  { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name_raw);
2822  if (maybe_symbol_version->ToObject(&symbol_version)) {
2823  name_raw = String::cast(symbol_version);
2824  }
2825  }
2826  }
2827 
2828  // Check access rights if needed.
2829  if (IsAccessCheckNeeded()) {
2830  if (!heap->isolate()->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
2832  result, name_raw, value_raw, true, strict_mode);
2833  }
2834  }
2835 
2836  if (IsJSGlobalProxy()) {
2837  Object* proto = GetPrototype();
2838  if (proto->IsNull()) return value_raw;
2839  ASSERT(proto->IsJSGlobalObject());
2840  return JSObject::cast(proto)->SetPropertyForResult(
2841  result, name_raw, value_raw, attributes, strict_mode, store_mode);
2842  }
2843 
2844  // From this point on everything needs to be handlified, because
2845  // SetPropertyViaPrototypes might call back into JavaScript.
2846  HandleScope scope(GetIsolate());
2847  Handle<JSObject> self(this);
2848  Handle<String> name(name_raw);
2849  Handle<Object> value(value_raw);
2850 
2851  if (!result->IsProperty() && !self->IsJSContextExtensionObject()) {
2852  bool done = false;
2853  MaybeObject* result_object = self->SetPropertyViaPrototypes(
2854  *name, *value, attributes, strict_mode, &done);
2855  if (done) return result_object;
2856  }
2857 
2858  if (!result->IsFound()) {
2859  // Neither properties nor transitions found.
2860  return self->AddProperty(
2861  *name, *value, attributes, strict_mode, store_mode);
2862  }
2863  if (result->IsProperty() && result->IsReadOnly()) {
2864  if (strict_mode == kStrictMode) {
2865  Handle<Object> args[] = { name, self };
2866  return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
2867  "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2868  } else {
2869  return *value;
2870  }
2871  }
2872 
2873  // This is a real property that is not read-only, or it is a
2874  // transition or null descriptor and there are no setters in the prototypes.
2875  switch (result->type()) {
2876  case NORMAL:
2877  return self->SetNormalizedProperty(result, *value);
2878  case FIELD:
2879  return self->FastPropertyAtPut(result->GetFieldIndex(), *value);
2880  case CONSTANT_FUNCTION:
2881  // Only replace the function if necessary.
2882  if (*value == result->GetConstantFunction()) return *value;
2883  // Preserve the attributes of this existing property.
2884  attributes = result->GetAttributes();
2885  return self->ConvertDescriptorToField(*name, *value, attributes);
2886  case CALLBACKS: {
2887  Object* callback_object = result->GetCallbackObject();
2888  return self->SetPropertyWithCallback(callback_object,
2889  *name,
2890  *value,
2891  result->holder(),
2892  strict_mode);
2893  }
2894  case INTERCEPTOR:
2895  return self->SetPropertyWithInterceptor(*name,
2896  *value,
2897  attributes,
2898  strict_mode);
2899  case TRANSITION: {
2900  Map* transition_map = result->GetTransitionTarget();
2901  int descriptor = transition_map->LastAdded();
2902 
2903  DescriptorArray* descriptors = transition_map->instance_descriptors();
2904  PropertyDetails details = descriptors->GetDetails(descriptor);
2905 
2906  if (details.type() == FIELD) {
2907  if (attributes == details.attributes()) {
2908  int field_index = descriptors->GetFieldIndex(descriptor);
2909  return self->AddFastPropertyUsingMap(transition_map,
2910  *name,
2911  *value,
2912  field_index);
2913  }
2914  return self->ConvertDescriptorToField(*name, *value, attributes);
2915  } else if (details.type() == CALLBACKS) {
2916  return ConvertDescriptorToField(*name, *value, attributes);
2917  }
2918 
2919  ASSERT(details.type() == CONSTANT_FUNCTION);
2920 
2921  Object* constant_function = descriptors->GetValue(descriptor);
2922  // If the same constant function is being added we can simply
2923  // transition to the target map.
2924  if (constant_function == *value) {
2925  self->set_map(transition_map);
2926  return constant_function;
2927  }
2928  // Otherwise, replace with a map transition to a new map with a FIELD,
2929  // even if the value is a constant function.
2931  result->GetTransitionIndex(), *name, *value, attributes);
2932  }
2933  case HANDLER:
2934  case NONEXISTENT:
2935  UNREACHABLE();
2936  return *value;
2937  }
2938  UNREACHABLE(); // keep the compiler happy
2939  return *value;
2940 }
2941 
2942 
2943 // Set a real local property, even if it is READ_ONLY. If the property is not
2944 // present, add it with attributes NONE. This code is an exact clone of
2945 // SetProperty, with the check for IsReadOnly and the check for a
2946 // callback setter removed. The two lines looking up the LookupResult
2947 // result are also added. If one of the functions is changed, the other
2948 // should be.
2949 // Note that this method cannot be used to set the prototype of a function
2950 // because ConvertDescriptorToField() which is called in "case CALLBACKS:"
2951 // doesn't handle function prototypes correctly.
2953  Handle<JSObject> object,
2954  Handle<String> key,
2955  Handle<Object> value,
2956  PropertyAttributes attributes) {
2958  object->GetIsolate(),
2959  object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
2960  Object);
2961 }
2962 
2963 
2965  String* name,
2966  Object* value,
2967  PropertyAttributes attributes) {
2968  // Make sure that the top context does not change when doing callbacks or
2969  // interceptor calls.
2970  AssertNoContextChange ncc;
2971  Isolate* isolate = GetIsolate();
2972  LookupResult result(isolate);
2973  LocalLookup(name, &result);
2974  if (!result.IsFound()) map()->LookupTransition(this, name, &result);
2975  // Check access rights if needed.
2976  if (IsAccessCheckNeeded()) {
2977  if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
2978  return SetPropertyWithFailedAccessCheck(&result,
2979  name,
2980  value,
2981  false,
2982  kNonStrictMode);
2983  }
2984  }
2985 
2986  if (IsJSGlobalProxy()) {
2987  Object* proto = GetPrototype();
2988  if (proto->IsNull()) return value;
2989  ASSERT(proto->IsJSGlobalObject());
2991  name,
2992  value,
2993  attributes);
2994  }
2995 
2996  // Check for accessor in prototype chain removed here in clone.
2997  if (!result.IsFound()) {
2998  // Neither properties nor transitions found.
2999  return AddProperty(name, value, attributes, kNonStrictMode);
3000  }
3001 
3002  // Check of IsReadOnly removed from here in clone.
3003  switch (result.type()) {
3004  case NORMAL: {
3005  PropertyDetails details = PropertyDetails(attributes, NORMAL);
3006  return SetNormalizedProperty(name, value, details);
3007  }
3008  case FIELD:
3009  return FastPropertyAtPut(result.GetFieldIndex(), value);
3010  case CONSTANT_FUNCTION:
3011  // Only replace the function if necessary.
3012  if (value == result.GetConstantFunction()) return value;
3013  // Preserve the attributes of this existing property.
3014  attributes = result.GetAttributes();
3015  return ConvertDescriptorToField(name, value, attributes);
3016  case CALLBACKS:
3017  case INTERCEPTOR:
3018  // Override callback in clone
3019  return ConvertDescriptorToField(name, value, attributes);
3020  case TRANSITION: {
3021  Map* transition_map = result.GetTransitionTarget();
3022  int descriptor = transition_map->LastAdded();
3023 
3024  DescriptorArray* descriptors = transition_map->instance_descriptors();
3025  PropertyDetails details = descriptors->GetDetails(descriptor);
3026 
3027  if (details.type() == FIELD) {
3028  if (attributes == details.attributes()) {
3029  int field_index = descriptors->GetFieldIndex(descriptor);
3030  return AddFastPropertyUsingMap(transition_map,
3031  name,
3032  value,
3033  field_index);
3034  }
3035  return ConvertDescriptorToField(name, value, attributes);
3036  } else if (details.type() == CALLBACKS) {
3037  return ConvertDescriptorToField(name, value, attributes);
3038  }
3039 
3040  ASSERT(details.type() == CONSTANT_FUNCTION);
3041 
3042  // Replace transition to CONSTANT FUNCTION with a map transition to a new
3043  // map with a FIELD, even if the value is a function.
3045  result.GetTransitionIndex(), name, value, attributes);
3046  }
3047  case HANDLER:
3048  case NONEXISTENT:
3049  UNREACHABLE();
3050  }
3051  UNREACHABLE(); // keep the compiler happy
3052  return value;
3053 }
3054 
3055 
3057  JSObject* receiver,
3058  String* name,
3059  bool continue_search) {
3060  // Check local property, ignore interceptor.
3061  LookupResult result(GetIsolate());
3062  LocalLookupRealNamedProperty(name, &result);
3063  if (result.IsFound()) return result.GetAttributes();
3064 
3065  if (continue_search) {
3066  // Continue searching via the prototype chain.
3067  Object* pt = GetPrototype();
3068  if (!pt->IsNull()) {
3069  return JSObject::cast(pt)->
3070  GetPropertyAttributeWithReceiver(receiver, name);
3071  }
3072  }
3073  return ABSENT;
3074 }
3075 
3076 
3078  JSObject* receiver,
3079  String* name,
3080  bool continue_search) {
3081  Isolate* isolate = GetIsolate();
3082 
3083  // Make sure that the top context does not change when doing
3084  // callbacks or interceptor calls.
3085  AssertNoContextChange ncc;
3086 
3087  HandleScope scope(isolate);
3089  Handle<JSObject> receiver_handle(receiver);
3090  Handle<JSObject> holder_handle(this);
3091  Handle<String> name_handle(name);
3092  CustomArguments args(isolate, interceptor->data(), receiver, this);
3093  v8::AccessorInfo info(args.end());
3094  if (!interceptor->query()->IsUndefined()) {
3095  v8::NamedPropertyQuery query =
3096  v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
3097  LOG(isolate,
3098  ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
3099  v8::Handle<v8::Integer> result;
3100  {
3101  // Leaving JavaScript.
3102  VMState state(isolate, EXTERNAL);
3103  result = query(v8::Utils::ToLocal(name_handle), info);
3104  }
3105  if (!result.IsEmpty()) {
3106  ASSERT(result->IsInt32());
3107  return static_cast<PropertyAttributes>(result->Int32Value());
3108  }
3109  } else if (!interceptor->getter()->IsUndefined()) {
3110  v8::NamedPropertyGetter getter =
3111  v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
3112  LOG(isolate,
3113  ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
3114  v8::Handle<v8::Value> result;
3115  {
3116  // Leaving JavaScript.
3117  VMState state(isolate, EXTERNAL);
3118  result = getter(v8::Utils::ToLocal(name_handle), info);
3119  }
3120  if (!result.IsEmpty()) return DONT_ENUM;
3121  }
3122  return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
3123  *name_handle,
3124  continue_search);
3125 }
3126 
3127 
3129  JSReceiver* receiver,
3130  String* key) {
3131  uint32_t index = 0;
3132  if (IsJSObject() && key->AsArrayIndex(&index)) {
3133  return JSObject::cast(this)->HasElementWithReceiver(receiver, index)
3134  ? NONE : ABSENT;
3135  }
3136  // Named property.
3137  LookupResult result(GetIsolate());
3138  Lookup(key, &result);
3139  return GetPropertyAttribute(receiver, &result, key, true);
3140 }
3141 
3142 
3144  LookupResult* result,
3145  String* name,
3146  bool continue_search) {
3147  // Check access rights if needed.
3148  if (IsAccessCheckNeeded()) {
3149  JSObject* this_obj = JSObject::cast(this);
3150  Heap* heap = GetHeap();
3151  if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
3153  receiver, result, name, continue_search);
3154  }
3155  }
3156  if (result->IsFound()) {
3157  switch (result->type()) {
3158  case NORMAL: // fall through
3159  case FIELD:
3160  case CONSTANT_FUNCTION:
3161  case CALLBACKS:
3162  return result->GetAttributes();
3163  case HANDLER: {
3164  return JSProxy::cast(result->proxy())->GetPropertyAttributeWithHandler(
3165  receiver, name);
3166  }
3167  case INTERCEPTOR:
3168  return result->holder()->GetPropertyAttributeWithInterceptor(
3169  JSObject::cast(receiver), name, continue_search);
3170  case TRANSITION:
3171  case NONEXISTENT:
3172  UNREACHABLE();
3173  }
3174  }
3175  return ABSENT;
3176 }
3177 
3178 
3180  // Check whether the name is an array index.
3181  uint32_t index = 0;
3182  if (IsJSObject() && name->AsArrayIndex(&index)) {
3183  if (JSObject::cast(this)->HasLocalElement(index)) return NONE;
3184  return ABSENT;
3185  }
3186  // Named property.
3187  LookupResult result(GetIsolate());
3188  LocalLookup(name, &result);
3189  return GetPropertyAttribute(this, &result, name, false);
3190 }
3191 
3192 
3195  Isolate* isolate = obj->GetIsolate();
3196  Map* fast = obj->map();
3197  int index = fast->Hash() % kEntries;
3198  Object* result = get(index);
3199  if (result->IsMap() &&
3200  Map::cast(result)->EquivalentToForNormalization(fast, mode)) {
3201 #ifdef VERIFY_HEAP
3202  if (FLAG_verify_heap) {
3203  Map::cast(result)->SharedMapVerify();
3204  }
3205 #endif
3206 #ifdef DEBUG
3208  // The cached map should match newly created normalized map bit-by-bit,
3209  // except for the code cache, which can contain some ics which can be
3210  // applied to the shared map.
3211  Object* fresh;
3212  MaybeObject* maybe_fresh =
3214  if (maybe_fresh->ToObject(&fresh)) {
3215  ASSERT(memcmp(Map::cast(fresh)->address(),
3216  Map::cast(result)->address(),
3217  Map::kCodeCacheOffset) == 0);
3218  int offset = Map::kCodeCacheOffset + kPointerSize;
3219  ASSERT(memcmp(Map::cast(fresh)->address() + offset,
3220  Map::cast(result)->address() + offset,
3221  Map::kSize - offset) == 0);
3222  }
3223  }
3224 #endif
3225  return result;
3226  }
3227 
3228  { MaybeObject* maybe_result =
3230  if (!maybe_result->ToObject(&result)) return maybe_result;
3231  }
3232  ASSERT(Map::cast(result)->is_dictionary_map());
3233  set(index, result);
3234  isolate->counters()->normalized_maps()->Increment();
3235 
3236  return result;
3237 }
3238 
3239 
3241  int entries = length();
3242  for (int i = 0; i != entries; i++) {
3243  set_undefined(i);
3244  }
3245 }
3246 
3247 
3249  Handle<String> name,
3250  Handle<Code> code) {
3251  Isolate* isolate = object->GetIsolate();
3252  CALL_HEAP_FUNCTION_VOID(isolate,
3253  object->UpdateMapCodeCache(*name, *code));
3254 }
3255 
3256 
3258  if (map()->is_shared()) {
3259  // Fast case maps are never marked as shared.
3261  // Replace the map with an identical copy that can be safely modified.
3262  Object* obj;
3263  { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES,
3265  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3266  }
3267  GetIsolate()->counters()->normalized_maps()->Increment();
3268 
3269  set_map(Map::cast(obj));
3270  }
3271  return map()->UpdateCodeCache(name, code);
3272 }
3273 
3274 
3277  int expected_additional_properties) {
3278  CALL_HEAP_FUNCTION_VOID(object->GetIsolate(),
3279  object->NormalizeProperties(
3280  mode, expected_additional_properties));
3281 }
3282 
3283 
3285  int expected_additional_properties) {
3286  if (!HasFastProperties()) return this;
3287 
3288  // The global object is always normalized.
3289  ASSERT(!IsGlobalObject());
3290  // JSGlobalProxy must never be normalized
3291  ASSERT(!IsJSGlobalProxy());
3292 
3293  Map* map_of_this = map();
3294 
3295  // Allocate new content.
3296  int real_size = map_of_this->NumberOfOwnDescriptors();
3297  int property_count = real_size;
3298  if (expected_additional_properties > 0) {
3299  property_count += expected_additional_properties;
3300  } else {
3301  property_count += 2; // Make space for two more properties.
3302  }
3303  StringDictionary* dictionary;
3304  MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
3305  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3306 
3307  DescriptorArray* descs = map_of_this->instance_descriptors();
3308  for (int i = 0; i < real_size; i++) {
3309  PropertyDetails details = descs->GetDetails(i);
3310  switch (details.type()) {
3311  case CONSTANT_FUNCTION: {
3312  PropertyDetails d = PropertyDetails(details.attributes(),
3313  NORMAL,
3314  details.descriptor_index());
3315  Object* value = descs->GetConstantFunction(i);
3316  MaybeObject* maybe_dictionary =
3317  dictionary->Add(descs->GetKey(i), value, d);
3318  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3319  break;
3320  }
3321  case FIELD: {
3322  PropertyDetails d = PropertyDetails(details.attributes(),
3323  NORMAL,
3324  details.descriptor_index());
3325  Object* value = FastPropertyAt(descs->GetFieldIndex(i));
3326  MaybeObject* maybe_dictionary =
3327  dictionary->Add(descs->GetKey(i), value, d);
3328  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3329  break;
3330  }
3331  case CALLBACKS: {
3332  Object* value = descs->GetCallbacksObject(i);
3333  details = details.set_pointer(0);
3334  MaybeObject* maybe_dictionary =
3335  dictionary->Add(descs->GetKey(i), value, details);
3336  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3337  break;
3338  }
3339  case INTERCEPTOR:
3340  break;
3341  case HANDLER:
3342  case NORMAL:
3343  case TRANSITION:
3344  case NONEXISTENT:
3345  UNREACHABLE();
3346  break;
3347  }
3348  }
3349 
3350  Heap* current_heap = GetHeap();
3351 
3352  // Copy the next enumeration index from instance descriptor.
3353  dictionary->SetNextEnumerationIndex(real_size + 1);
3354 
3355  Map* new_map;
3356  MaybeObject* maybe_map =
3357  current_heap->isolate()->context()->native_context()->
3358  normalized_map_cache()->Get(this, mode);
3359  if (!maybe_map->To(&new_map)) return maybe_map;
3360  ASSERT(new_map->is_dictionary_map());
3361 
3362  // We have now successfully allocated all the necessary objects.
3363  // Changes can now be made with the guarantee that all of them take effect.
3364 
3365  // Resize the object in the heap if necessary.
3366  int new_instance_size = new_map->instance_size();
3367  int instance_size_delta = map_of_this->instance_size() - new_instance_size;
3368  ASSERT(instance_size_delta >= 0);
3369  current_heap->CreateFillerObjectAt(this->address() + new_instance_size,
3370  instance_size_delta);
3373  -instance_size_delta);
3374  }
3375 
3376  set_map(new_map);
3377 
3378  set_properties(dictionary);
3379 
3380  current_heap->isolate()->counters()->props_to_dictionary()->Increment();
3381 
3382 #ifdef DEBUG
3383  if (FLAG_trace_normalization) {
3384  PrintF("Object properties have been normalized:\n");
3385  Print();
3386  }
3387 #endif
3388  return this;
3389 }
3390 
3391 
3393  int unused_property_fields) {
3395  object->GetIsolate(),
3396  object->TransformToFastProperties(unused_property_fields));
3397 }
3398 
3399 
3400 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
3401  if (HasFastProperties()) return this;
3402  ASSERT(!IsGlobalObject());
3403  return property_dictionary()->
3404  TransformPropertiesToFastFor(this, unused_property_fields);
3405 }
3406 
3407 
3409  Handle<JSObject> object) {
3410  CALL_HEAP_FUNCTION(object->GetIsolate(),
3411  object->NormalizeElements(),
3413 }
3414 
3415 
3418 
3419  // Find the backing store.
3420  FixedArrayBase* array = FixedArrayBase::cast(elements());
3421  Map* old_map = array->map();
3422  bool is_arguments =
3423  (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
3424  if (is_arguments) {
3425  array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
3426  }
3427  if (array->IsDictionary()) return array;
3428 
3432  // Compute the effective length and allocate a new backing store.
3433  int length = IsJSArray()
3434  ? Smi::cast(JSArray::cast(this)->length())->value()
3435  : array->length();
3436  int old_capacity = 0;
3437  int used_elements = 0;
3438  GetElementsCapacityAndUsage(&old_capacity, &used_elements);
3439  SeededNumberDictionary* dictionary = NULL;
3440  { Object* object;
3441  MaybeObject* maybe = SeededNumberDictionary::Allocate(used_elements);
3442  if (!maybe->ToObject(&object)) return maybe;
3443  dictionary = SeededNumberDictionary::cast(object);
3444  }
3445 
3446  // Copy the elements to the new backing store.
3447  bool has_double_elements = array->IsFixedDoubleArray();
3448  for (int i = 0; i < length; i++) {
3449  Object* value = NULL;
3450  if (has_double_elements) {
3451  FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
3452  if (double_array->is_the_hole(i)) {
3453  value = GetIsolate()->heap()->the_hole_value();
3454  } else {
3455  // Objects must be allocated in the old object space, since the
3456  // overall number of HeapNumbers needed for the conversion might
3457  // exceed the capacity of new space, and we would fail repeatedly
3458  // trying to convert the FixedDoubleArray.
3459  MaybeObject* maybe_value_object =
3460  GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
3461  if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
3462  }
3463  } else {
3465  value = FixedArray::cast(array)->get(i);
3466  }
3467  PropertyDetails details = PropertyDetails(NONE, NORMAL);
3468  if (!value->IsTheHole()) {
3469  Object* result;
3470  MaybeObject* maybe_result =
3471  dictionary->AddNumberEntry(i, value, details);
3472  if (!maybe_result->ToObject(&result)) return maybe_result;
3473  dictionary = SeededNumberDictionary::cast(result);
3474  }
3475  }
3476 
3477  // Switch to using the dictionary as the backing storage for elements.
3478  if (is_arguments) {
3479  FixedArray::cast(elements())->set(1, dictionary);
3480  } else {
3481  // Set the new map first to satify the elements type assert in
3482  // set_elements().
3483  Object* new_map;
3484  MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(),
3486  if (!maybe->ToObject(&new_map)) return maybe;
3487  set_map(Map::cast(new_map));
3488  set_elements(dictionary);
3489  }
3490 
3491  old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->
3492  Increment();
3493 
3494 #ifdef DEBUG
3495  if (FLAG_trace_normalization) {
3496  PrintF("Object elements have been normalized:\n");
3497  Print();
3498  }
3499 #endif
3500 
3502  return dictionary;
3503 }
3504 
3505 
3507  Isolate* isolate = GetIsolate();
3508 
3509  int hash_value;
3510  int attempts = 0;
3511  do {
3512  // Generate a random 32-bit hash value but limit range to fit
3513  // within a smi.
3514  hash_value = V8::RandomPrivate(isolate) & Smi::kMaxValue;
3515  attempts++;
3516  } while (hash_value == 0 && attempts < 30);
3517  hash_value = hash_value != 0 ? hash_value : 1; // never return 0
3518 
3519  return Smi::FromInt(hash_value);
3520 }
3521 
3522 
3524  MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3525  hash);
3526  if (maybe->IsFailure()) return maybe;
3527  return this;
3528 }
3529 
3530 
3532  CALL_AND_RETRY(obj->GetIsolate(),
3533  obj->GetIdentityHash(ALLOW_CREATION),
3534  return Smi::cast(__object__)->value(),
3535  return 0);
3536 }
3537 
3538 
3540  Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol());
3541  if (stored_value->IsSmi()) return stored_value;
3542 
3543  // Do not generate permanent identity hash code if not requested.
3544  if (flag == OMIT_CREATION) return GetHeap()->undefined_value();
3545 
3546  Smi* hash = GenerateIdentityHash();
3547  MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3548  hash);
3549  if (result->IsFailure()) return result;
3550  if (result->ToObjectUnchecked()->IsUndefined()) {
3551  // Trying to get hash of detached proxy.
3552  return Smi::FromInt(0);
3553  }
3554  return hash;
3555 }
3556 
3557 
3559  Object* hash = this->hash();
3560  if (!hash->IsSmi() && flag == ALLOW_CREATION) {
3561  hash = GenerateIdentityHash();
3562  set_hash(hash);
3563  }
3564  return hash;
3565 }
3566 
3567 
3569  ASSERT(key->IsSymbol());
3570  if (IsJSGlobalProxy()) {
3571  // For a proxy, use the prototype as target object.
3572  Object* proxy_parent = GetPrototype();
3573  // If the proxy is detached, return undefined.
3574  if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3575  ASSERT(proxy_parent->IsJSGlobalObject());
3576  return JSObject::cast(proxy_parent)->GetHiddenProperty(key);
3577  }
3578  ASSERT(!IsJSGlobalProxy());
3579  MaybeObject* hidden_lookup =
3580  GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE);
3581  Object* inline_value = hidden_lookup->ToObjectUnchecked();
3582 
3583  if (inline_value->IsSmi()) {
3584  // Handle inline-stored identity hash.
3585  if (key == GetHeap()->identity_hash_symbol()) {
3586  return inline_value;
3587  } else {
3588  return GetHeap()->undefined_value();
3589  }
3590  }
3591 
3592  if (inline_value->IsUndefined()) return GetHeap()->undefined_value();
3593 
3594  ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
3595  Object* entry = hashtable->Lookup(key);
3596  if (entry->IsTheHole()) return GetHeap()->undefined_value();
3597  return entry;
3598 }
3599 
3600 
3602  Handle<String> key,
3603  Handle<Object> value) {
3604  CALL_HEAP_FUNCTION(obj->GetIsolate(),
3605  obj->SetHiddenProperty(*key, *value),
3606  Object);
3607 }
3608 
3609 
3610 MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
3611  ASSERT(key->IsSymbol());
3612  if (IsJSGlobalProxy()) {
3613  // For a proxy, use the prototype as target object.
3614  Object* proxy_parent = GetPrototype();
3615  // If the proxy is detached, return undefined.
3616  if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3617  ASSERT(proxy_parent->IsJSGlobalObject());
3618  return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value);
3619  }
3620  ASSERT(!IsJSGlobalProxy());
3621  MaybeObject* hidden_lookup =
3622  GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE);
3623  Object* inline_value = hidden_lookup->ToObjectUnchecked();
3624 
3625  // If there is no backing store yet, store the identity hash inline.
3626  if (value->IsSmi() &&
3627  key == GetHeap()->identity_hash_symbol() &&
3628  (inline_value->IsUndefined() || inline_value->IsSmi())) {
3629  return SetHiddenPropertiesHashTable(value);
3630  }
3631 
3632  hidden_lookup = GetHiddenPropertiesHashTable(CREATE_NEW_IF_ABSENT);
3633  ObjectHashTable* hashtable;
3634  if (!hidden_lookup->To(&hashtable)) return hidden_lookup;
3635 
3636  // If it was found, check if the key is already in the dictionary.
3637  MaybeObject* insert_result = hashtable->Put(key, value);
3638  ObjectHashTable* new_table;
3639  if (!insert_result->To(&new_table)) return insert_result;
3640  if (new_table != hashtable) {
3641  // If adding the key expanded the dictionary (i.e., Add returned a new
3642  // dictionary), store it back to the object.
3643  MaybeObject* store_result = SetHiddenPropertiesHashTable(new_table);
3644  if (store_result->IsFailure()) return store_result;
3645  }
3646  // Return this to mark success.
3647  return this;
3648 }
3649 
3650 
3652  ASSERT(key->IsSymbol());
3653  if (IsJSGlobalProxy()) {
3654  // For a proxy, use the prototype as target object.
3655  Object* proxy_parent = GetPrototype();
3656  // If the proxy is detached, return immediately.
3657  if (proxy_parent->IsNull()) return;
3658  ASSERT(proxy_parent->IsJSGlobalObject());
3659  JSObject::cast(proxy_parent)->DeleteHiddenProperty(key);
3660  return;
3661  }
3662  ASSERT(!IsJSGlobalProxy());
3663  MaybeObject* hidden_lookup =
3664  GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE);
3665  Object* inline_value = hidden_lookup->ToObjectUnchecked();
3666 
3667  // We never delete (inline-stored) identity hashes.
3668  ASSERT(key != GetHeap()->identity_hash_symbol());
3669  if (inline_value->IsUndefined() || inline_value->IsSmi()) return;
3670 
3671  ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
3672  MaybeObject* delete_result = hashtable->Put(key, GetHeap()->the_hole_value());
3673  USE(delete_result);
3674  ASSERT(!delete_result->IsFailure()); // Delete does not cause GC.
3675 }
3676 
3677 
3680  GetHeap()->hidden_symbol(),
3681  false) != ABSENT;
3682 }
3683 
3684 
3685 MaybeObject* JSObject::GetHiddenPropertiesHashTable(
3686  InitializeHiddenProperties init_option) {
3687  ASSERT(!IsJSGlobalProxy());
3688  Object* inline_value;
3689  if (HasFastProperties()) {
3690  // If the object has fast properties, check whether the first slot
3691  // in the descriptor array matches the hidden symbol. Since the
3692  // hidden symbols hash code is zero (and no other string has hash
3693  // code zero) it will always occupy the first entry if present.
3694  DescriptorArray* descriptors = this->map()->instance_descriptors();
3695  if (descriptors->number_of_descriptors() > 0) {
3696  int sorted_index = descriptors->GetSortedKeyIndex(0);
3697  if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() &&
3698  sorted_index < map()->NumberOfOwnDescriptors()) {
3699  ASSERT(descriptors->GetType(sorted_index) == FIELD);
3700  inline_value =
3701  this->FastPropertyAt(descriptors->GetFieldIndex(sorted_index));
3702  } else {
3703  inline_value = GetHeap()->undefined_value();
3704  }
3705  } else {
3706  inline_value = GetHeap()->undefined_value();
3707  }
3708  } else {
3709  PropertyAttributes attributes;
3710  // You can't install a getter on a property indexed by the hidden symbol,
3711  // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3712  // object.
3713  inline_value =
3715  GetHeap()->hidden_symbol(),
3716  &attributes)->ToObjectUnchecked();
3717  }
3718 
3719  if (init_option == ONLY_RETURN_INLINE_VALUE ||
3720  inline_value->IsHashTable()) {
3721  return inline_value;
3722  }
3723 
3724  ObjectHashTable* hashtable;
3725  static const int kInitialCapacity = 4;
3726  MaybeObject* maybe_obj =
3727  ObjectHashTable::Allocate(kInitialCapacity,
3729  if (!maybe_obj->To<ObjectHashTable>(&hashtable)) return maybe_obj;
3730 
3731  if (inline_value->IsSmi()) {
3732  // We were storing the identity hash inline and now allocated an actual
3733  // dictionary. Put the identity hash into the new dictionary.
3734  MaybeObject* insert_result =
3735  hashtable->Put(GetHeap()->identity_hash_symbol(), inline_value);
3736  ObjectHashTable* new_table;
3737  if (!insert_result->To(&new_table)) return insert_result;
3738  // We expect no resizing for the first insert.
3739  ASSERT_EQ(hashtable, new_table);
3740  }
3741 
3742  MaybeObject* store_result =
3743  SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3744  hashtable,
3745  DONT_ENUM,
3748  if (store_result->IsFailure()) return store_result;
3749  return hashtable;
3750 }
3751 
3752 
3753 MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) {
3754  ASSERT(!IsJSGlobalProxy());
3755  // We can store the identity hash inline iff there is no backing store
3756  // for hidden properties yet.
3757  ASSERT(HasHiddenProperties() != value->IsSmi());
3758  if (HasFastProperties()) {
3759  // If the object has fast properties, check whether the first slot
3760  // in the descriptor array matches the hidden symbol. Since the
3761  // hidden symbols hash code is zero (and no other string has hash
3762  // code zero) it will always occupy the first entry if present.
3763  DescriptorArray* descriptors = this->map()->instance_descriptors();
3764  if (descriptors->number_of_descriptors() > 0) {
3765  int sorted_index = descriptors->GetSortedKeyIndex(0);
3766  if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() &&
3767  sorted_index < map()->NumberOfOwnDescriptors()) {
3768  ASSERT(descriptors->GetType(sorted_index) == FIELD);
3769  this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index),
3770  value);
3771  return this;
3772  }
3773  }
3774  }
3775  MaybeObject* store_result =
3776  SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3777  value,
3778  DONT_ENUM,
3781  if (store_result->IsFailure()) return store_result;
3782  return this;
3783 }
3784 
3785 
3786 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
3787  DeleteMode mode) {
3788  // Check local property, ignore interceptor.
3789  LookupResult result(GetIsolate());
3790  LocalLookupRealNamedProperty(name, &result);
3791  if (!result.IsFound()) return GetHeap()->true_value();
3792 
3793  // Normalize object if needed.
3794  Object* obj;
3795  { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3796  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3797  }
3798 
3799  return DeleteNormalizedProperty(name, mode);
3800 }
3801 
3802 
3803 MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) {
3804  Isolate* isolate = GetIsolate();
3805  HandleScope scope(isolate);
3806  Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
3807  Handle<String> name_handle(name);
3808  Handle<JSObject> this_handle(this);
3809  if (!interceptor->deleter()->IsUndefined()) {
3810  v8::NamedPropertyDeleter deleter =
3811  v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter());
3812  LOG(isolate,
3813  ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name));
3814  CustomArguments args(isolate, interceptor->data(), this, this);
3815  v8::AccessorInfo info(args.end());
3816  v8::Handle<v8::Boolean> result;
3817  {
3818  // Leaving JavaScript.
3819  VMState state(isolate, EXTERNAL);
3820  result = deleter(v8::Utils::ToLocal(name_handle), info);
3821  }
3823  if (!result.IsEmpty()) {
3824  ASSERT(result->IsBoolean());
3825  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
3826  result_internal->VerifyApiCallResultType();
3827  return *result_internal;
3828  }
3829  }
3830  MaybeObject* raw_result =
3831  this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION);
3833  return raw_result;
3834 }
3835 
3836 
3837 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
3838  Isolate* isolate = GetIsolate();
3839  Heap* heap = isolate->heap();
3840  // Make sure that the top context does not change when doing
3841  // callbacks or interceptor calls.
3842  AssertNoContextChange ncc;
3843  HandleScope scope(isolate);
3844  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
3845  if (interceptor->deleter()->IsUndefined()) return heap->false_value();
3846  v8::IndexedPropertyDeleter deleter =
3847  v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
3848  Handle<JSObject> this_handle(this);
3849  LOG(isolate,
3850  ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
3851  CustomArguments args(isolate, interceptor->data(), this, this);
3852  v8::AccessorInfo info(args.end());
3853  v8::Handle<v8::Boolean> result;
3854  {
3855  // Leaving JavaScript.
3856  VMState state(isolate, EXTERNAL);
3857  result = deleter(index, info);
3858  }
3860  if (!result.IsEmpty()) {
3861  ASSERT(result->IsBoolean());
3862  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
3863  result_internal->VerifyApiCallResultType();
3864  return *result_internal;
3865  }
3866  MaybeObject* raw_result = this_handle->GetElementsAccessor()->Delete(
3867  *this_handle,
3868  index,
3869  NORMAL_DELETION);
3871  return raw_result;
3872 }
3873 
3874 
3876  uint32_t index) {
3877  CALL_HEAP_FUNCTION(obj->GetIsolate(),
3878  obj->DeleteElement(index, JSObject::NORMAL_DELETION),
3879  Object);
3880 }
3881 
3882 
3883 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
3884  Isolate* isolate = GetIsolate();
3885  // Check access rights if needed.
3886  if (IsAccessCheckNeeded() &&
3887  !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
3889  return isolate->heap()->false_value();
3890  }
3891 
3892  if (IsStringObjectWithCharacterAt(index)) {
3893  if (mode == STRICT_DELETION) {
3894  // Deleting a non-configurable property in strict mode.
3895  HandleScope scope(isolate);
3896  Handle<Object> holder(this);
3897  Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
3898  Handle<Object> args[2] = { name, holder };
3899  Handle<Object> error =
3900  isolate->factory()->NewTypeError("strict_delete_property",
3901  HandleVector(args, 2));
3902  return isolate->Throw(*error);
3903  }
3904  return isolate->heap()->false_value();
3905  }
3906 
3907  if (IsJSGlobalProxy()) {
3908  Object* proto = GetPrototype();
3909  if (proto->IsNull()) return isolate->heap()->false_value();
3910  ASSERT(proto->IsJSGlobalObject());
3911  return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
3912  }
3913 
3914  if (HasIndexedInterceptor()) {
3915  // Skip interceptor if forcing deletion.
3916  if (mode != FORCE_DELETION) {
3917  return DeleteElementWithInterceptor(index);
3918  }
3920  }
3921 
3922  return GetElementsAccessor()->Delete(this, index, mode);
3923 }
3924 
3925 
3927  Handle<String> prop) {
3928  CALL_HEAP_FUNCTION(obj->GetIsolate(),
3929  obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
3930  Object);
3931 }
3932 
3933 
3934 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
3935  Isolate* isolate = GetIsolate();
3936  // ECMA-262, 3rd, 8.6.2.5
3937  ASSERT(name->IsString());
3938 
3939  // Check access rights if needed.
3940  if (IsAccessCheckNeeded() &&
3941  !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) {
3943  return isolate->heap()->false_value();
3944  }
3945 
3946  if (IsJSGlobalProxy()) {
3947  Object* proto = GetPrototype();
3948  if (proto->IsNull()) return isolate->heap()->false_value();
3949  ASSERT(proto->IsJSGlobalObject());
3950  return JSGlobalObject::cast(proto)->DeleteProperty(name, mode);
3951  }
3952 
3953  uint32_t index = 0;
3954  if (name->AsArrayIndex(&index)) {
3955  return DeleteElement(index, mode);
3956  } else {
3957  LookupResult result(isolate);
3958  LocalLookup(name, &result);
3959  if (!result.IsFound()) return isolate->heap()->true_value();
3960  // Ignore attributes if forcing a deletion.
3961  if (result.IsDontDelete() && mode != FORCE_DELETION) {
3962  if (mode == STRICT_DELETION) {
3963  // Deleting a non-configurable property in strict mode.
3964  HandleScope scope(isolate);
3965  Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
3966  return isolate->Throw(*isolate->factory()->NewTypeError(
3967  "strict_delete_property", HandleVector(args, 2)));
3968  }
3969  return isolate->heap()->false_value();
3970  }
3971  // Check for interceptor.
3972  if (result.IsInterceptor()) {
3973  // Skip interceptor if forcing a deletion.
3974  if (mode == FORCE_DELETION) {
3975  return DeletePropertyPostInterceptor(name, mode);
3976  }
3977  return DeletePropertyWithInterceptor(name);
3978  }
3979  // Normalize object if needed.
3980  Object* obj;
3981  { MaybeObject* maybe_obj =
3983  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3984  }
3985  // Make sure the properties are normalized before removing the entry.
3986  return DeleteNormalizedProperty(name, mode);
3987  }
3988 }
3989 
3990 
3991 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) {
3992  if (IsJSProxy()) {
3993  return JSProxy::cast(this)->DeleteElementWithHandler(index, mode);
3994  }
3995  return JSObject::cast(this)->DeleteElement(index, mode);
3996 }
3997 
3998 
3999 MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
4000  if (IsJSProxy()) {
4001  return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
4002  }
4003  return JSObject::cast(this)->DeleteProperty(name, mode);
4004 }
4005 
4006 
4007 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
4008  ElementsKind kind,
4009  Object* object) {
4011  kind == DICTIONARY_ELEMENTS);
4012  if (IsFastObjectElementsKind(kind)) {
4013  int length = IsJSArray()
4014  ? Smi::cast(JSArray::cast(this)->length())->value()
4015  : elements->length();
4016  for (int i = 0; i < length; ++i) {
4017  Object* element = elements->get(i);
4018  if (!element->IsTheHole() && element == object) return true;
4019  }
4020  } else {
4021  Object* key =
4023  if (!key->IsUndefined()) return true;
4024  }
4025  return false;
4026 }
4027 
4028 
4029 // Check whether this object references another object.
4031  Map* map_of_this = map();
4032  Heap* heap = GetHeap();
4033  AssertNoAllocation no_alloc;
4034 
4035  // Is the object the constructor for this object?
4036  if (map_of_this->constructor() == obj) {
4037  return true;
4038  }
4039 
4040  // Is the object the prototype for this object?
4041  if (map_of_this->prototype() == obj) {
4042  return true;
4043  }
4044 
4045  // Check if the object is among the named properties.
4046  Object* key = SlowReverseLookup(obj);
4047  if (!key->IsUndefined()) {
4048  return true;
4049  }
4050 
4051  // Check if the object is among the indexed properties.
4052  ElementsKind kind = GetElementsKind();
4053  switch (kind) {
4059  case EXTERNAL_INT_ELEMENTS:
4063  case FAST_DOUBLE_ELEMENTS:
4065  // Raw pixels and external arrays do not reference other
4066  // objects.
4067  break;
4068  case FAST_SMI_ELEMENTS:
4070  break;
4071  case FAST_ELEMENTS:
4072  case FAST_HOLEY_ELEMENTS:
4073  case DICTIONARY_ELEMENTS: {
4074  FixedArray* elements = FixedArray::cast(this->elements());
4075  if (ReferencesObjectFromElements(elements, kind, obj)) return true;
4076  break;
4077  }
4079  FixedArray* parameter_map = FixedArray::cast(elements());
4080  // Check the mapped parameters.
4081  int length = parameter_map->length();
4082  for (int i = 2; i < length; ++i) {
4083  Object* value = parameter_map->get(i);
4084  if (!value->IsTheHole() && value == obj) return true;
4085  }
4086  // Check the arguments.
4087  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4088  kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
4090  if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
4091  break;
4092  }
4093  }
4094 
4095  // For functions check the context.
4096  if (IsJSFunction()) {
4097  // Get the constructor function for arguments array.
4098  JSObject* arguments_boilerplate =
4099  heap->isolate()->context()->native_context()->
4100  arguments_boilerplate();
4101  JSFunction* arguments_function =
4102  JSFunction::cast(arguments_boilerplate->map()->constructor());
4103 
4104  // Get the context and don't check if it is the native context.
4105  JSFunction* f = JSFunction::cast(this);
4106  Context* context = f->context();
4107  if (context->IsNativeContext()) {
4108  return false;
4109  }
4110 
4111  // Check the non-special context slots.
4112  for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
4113  // Only check JS objects.
4114  if (context->get(i)->IsJSObject()) {
4115  JSObject* ctxobj = JSObject::cast(context->get(i));
4116  // If it is an arguments array check the content.
4117  if (ctxobj->map()->constructor() == arguments_function) {
4118  if (ctxobj->ReferencesObject(obj)) {
4119  return true;
4120  }
4121  } else if (ctxobj == obj) {
4122  return true;
4123  }
4124  }
4125  }
4126 
4127  // Check the context extension (if any) if it can have references.
4128  if (context->has_extension() && !context->IsCatchContext()) {
4129  return JSObject::cast(context->extension())->ReferencesObject(obj);
4130  }
4131  }
4132 
4133  // No references to object.
4134  return false;
4135 }
4136 
4137 
4139  CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object);
4140 }
4141 
4142 
4144  Isolate* isolate = GetIsolate();
4145  if (IsAccessCheckNeeded() &&
4146  !isolate->MayNamedAccess(this,
4147  isolate->heap()->undefined_value(),
4148  v8::ACCESS_KEYS)) {
4149  isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
4150  return isolate->heap()->false_value();
4151  }
4152 
4153  if (IsJSGlobalProxy()) {
4154  Object* proto = GetPrototype();
4155  if (proto->IsNull()) return this;
4156  ASSERT(proto->IsJSGlobalObject());
4157  return JSObject::cast(proto)->PreventExtensions();
4158  }
4159 
4160  // It's not possible to seal objects with external array elements
4161  if (HasExternalArrayElements()) {
4162  HandleScope scope(isolate);
4163  Handle<Object> object(this);
4164  Handle<Object> error =
4165  isolate->factory()->NewTypeError(
4166  "cant_prevent_ext_external_array_elements",
4167  HandleVector(&object, 1));
4168  return isolate->Throw(*error);
4169  }
4170 
4171  // If there are fast elements we normalize.
4172  SeededNumberDictionary* dictionary = NULL;
4173  { MaybeObject* maybe = NormalizeElements();
4174  if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe;
4175  }
4177  // Make sure that we never go back to fast case.
4178  dictionary->set_requires_slow_elements();
4179 
4180  // Do a map transition, other objects with this map may still
4181  // be extensible.
4182  Map* new_map;
4183  MaybeObject* maybe = map()->Copy();
4184  if (!maybe->To(&new_map)) return maybe;
4185 
4186  new_map->set_is_extensible(false);
4187  set_map(new_map);
4188  ASSERT(!map()->is_extensible());
4189  return new_map;
4190 }
4191 
4192 
4193 // Tests for the fast common case for property enumeration:
4194 // - This object and all prototypes has an enum cache (which means that
4195 // it is no proxy, has no interceptors and needs no access checks).
4196 // - This object has no elements.
4197 // - No prototype has enumerable properties/elements.
4199  Heap* heap = GetHeap();
4200  for (Object* o = this;
4201  o != heap->null_value();
4202  o = JSObject::cast(o)->GetPrototype()) {
4203  if (!o->IsJSObject()) return false;
4204  JSObject* curr = JSObject::cast(o);
4205  int enum_length = curr->map()->EnumLength();
4206  if (enum_length == Map::kInvalidEnumCache) return false;
4207  ASSERT(!curr->HasNamedInterceptor());
4208  ASSERT(!curr->HasIndexedInterceptor());
4209  ASSERT(!curr->IsAccessCheckNeeded());
4210  if (curr->NumberOfEnumElements() > 0) return false;
4211  if (curr != this && enum_length != 0) return false;
4212  }
4213  return true;
4214 }
4215 
4216 
4218  PropertyAttributes filter) {
4219  int result = 0;
4220  DescriptorArray* descs = instance_descriptors();
4221  int limit = which == ALL_DESCRIPTORS
4222  ? descs->number_of_descriptors()
4223  : NumberOfOwnDescriptors();
4224  for (int i = 0; i < limit; i++) {
4225  if ((descs->GetDetails(i).attributes() & filter) == 0) result++;
4226  }
4227  return result;
4228 }
4229 
4230 
4232  DescriptorArray* descs = instance_descriptors();
4233  int limit = NumberOfOwnDescriptors();
4234  for (int i = 0; i < limit; i++) {
4235  if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i);
4236  }
4237  return -1;
4238 }
4239 
4240 
4242  int max_index = -1;
4243  int number_of_own_descriptors = NumberOfOwnDescriptors();
4244  DescriptorArray* descs = instance_descriptors();
4245  for (int i = 0; i < number_of_own_descriptors; i++) {
4246  if (descs->GetType(i) == FIELD) {
4247  int current_index = descs->GetFieldIndex(i);
4248  if (current_index > max_index) max_index = current_index;
4249  }
4250  }
4251  return max_index + 1;
4252 }
4253 
4254 
4256  DescriptorArray* descs = instance_descriptors();
4257  int number_of_own_descriptors = NumberOfOwnDescriptors();
4258  for (int i = 0; i < number_of_own_descriptors; i++) {
4259  if (descs->GetType(i) == CALLBACKS && name->Equals(descs->GetKey(i))) {
4260  return descs->GetCallbacks(i);
4261  }
4262  }
4263  return NULL;
4264 }
4265 
4266 
4267 void JSReceiver::LocalLookup(String* name, LookupResult* result) {
4268  ASSERT(name->IsString());
4269 
4270  Heap* heap = GetHeap();
4271 
4272  if (IsJSGlobalProxy()) {
4273  Object* proto = GetPrototype();
4274  if (proto->IsNull()) return result->NotFound();
4275  ASSERT(proto->IsJSGlobalObject());
4276  return JSReceiver::cast(proto)->LocalLookup(name, result);
4277  }
4278 
4279  if (IsJSProxy()) {
4280  result->HandlerResult(JSProxy::cast(this));
4281  return;
4282  }
4283 
4284  // Do not use inline caching if the object is a non-global object
4285  // that requires access checks.
4286  if (IsAccessCheckNeeded()) {
4287  result->DisallowCaching();
4288  }
4289 
4290  JSObject* js_object = JSObject::cast(this);
4291 
4292  // Check __proto__ before interceptor.
4293  if (name->Equals(heap->Proto_symbol()) && !IsJSContextExtensionObject()) {
4294  result->ConstantResult(js_object);
4295  return;
4296  }
4297 
4298  // Check for lookup interceptor except when bootstrapping.
4299  if (js_object->HasNamedInterceptor() &&
4300  !heap->isolate()->bootstrapper()->IsActive()) {
4301  result->InterceptorResult(js_object);
4302  return;
4303  }
4304 
4305  js_object->LocalLookupRealNamedProperty(name, result);
4306 }
4307 
4308 
4309 void JSReceiver::Lookup(String* name, LookupResult* result) {
4310  // Ecma-262 3rd 8.6.2.4
4311  Heap* heap = GetHeap();
4312  for (Object* current = this;
4313  current != heap->null_value();
4314  current = JSObject::cast(current)->GetPrototype()) {
4315  JSReceiver::cast(current)->LocalLookup(name, result);
4316  if (result->IsFound()) return;
4317  }
4318  result->NotFound();
4319 }
4320 
4321 
4322 // Search object and its prototype chain for callback properties.
4323 void JSObject::LookupCallbackProperty(String* name, LookupResult* result) {
4324  Heap* heap = GetHeap();
4325  for (Object* current = this;
4326  current != heap->null_value() && current->IsJSObject();
4327  current = JSObject::cast(current)->GetPrototype()) {
4328  JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
4329  if (result->IsPropertyCallbacks()) return;
4330  }
4331  result->NotFound();
4332 }
4333 
4334 
4335 // Try to update an accessor in an elements dictionary. Return true if the
4336 // update succeeded, and false otherwise.
4337 static bool UpdateGetterSetterInDictionary(
4338  SeededNumberDictionary* dictionary,
4339  uint32_t index,
4340  Object* getter,
4341  Object* setter,
4342  PropertyAttributes attributes) {
4343  int entry = dictionary->FindEntry(index);
4344  if (entry != SeededNumberDictionary::kNotFound) {
4345  Object* result = dictionary->ValueAt(entry);
4346  PropertyDetails details = dictionary->DetailsAt(entry);
4347  if (details.type() == CALLBACKS && result->IsAccessorPair()) {
4348  ASSERT(!details.IsDontDelete());
4349  if (details.attributes() != attributes) {
4350  dictionary->DetailsAtPut(entry,
4351  PropertyDetails(attributes, CALLBACKS, index));
4352  }
4353  AccessorPair::cast(result)->SetComponents(getter, setter);
4354  return true;
4355  }
4356  }
4357  return false;
4358 }
4359 
4360 
4361 MaybeObject* JSObject::DefineElementAccessor(uint32_t index,
4362  Object* getter,
4363  Object* setter,
4364  PropertyAttributes attributes) {
4365  switch (GetElementsKind()) {
4366  case FAST_SMI_ELEMENTS:
4367  case FAST_ELEMENTS:
4368  case FAST_DOUBLE_ELEMENTS:
4370  case FAST_HOLEY_ELEMENTS:
4372  break;
4378  case EXTERNAL_INT_ELEMENTS:
4382  // Ignore getters and setters on pixel and external array elements.
4383  return GetHeap()->undefined_value();
4384  case DICTIONARY_ELEMENTS:
4385  if (UpdateGetterSetterInDictionary(element_dictionary(),
4386  index,
4387  getter,
4388  setter,
4389  attributes)) {
4390  return GetHeap()->undefined_value();
4391  }
4392  break;
4394  // Ascertain whether we have read-only properties or an existing
4395  // getter/setter pair in an arguments elements dictionary backing
4396  // store.
4397  FixedArray* parameter_map = FixedArray::cast(elements());
4398  uint32_t length = parameter_map->length();
4399  Object* probe =
4400  index < (length - 2) ? parameter_map->get(index + 2) : NULL;
4401  if (probe == NULL || probe->IsTheHole()) {
4402  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4403  if (arguments->IsDictionary()) {
4404  SeededNumberDictionary* dictionary =
4405  SeededNumberDictionary::cast(arguments);
4406  if (UpdateGetterSetterInDictionary(dictionary,
4407  index,
4408  getter,
4409  setter,
4410  attributes)) {
4411  return GetHeap()->undefined_value();
4412  }
4413  }
4414  }
4415  break;
4416  }
4417  }
4418 
4419  AccessorPair* accessors;
4420  { MaybeObject* maybe_accessors = GetHeap()->AllocateAccessorPair();
4421  if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4422  }
4423  accessors->SetComponents(getter, setter);
4424 
4425  return SetElementCallback(index, accessors, attributes);
4426 }
4427 
4428 
4429 MaybeObject* JSObject::CreateAccessorPairFor(String* name) {
4430  LookupResult result(GetHeap()->isolate());
4431  LocalLookupRealNamedProperty(name, &result);
4432  if (result.IsPropertyCallbacks()) {
4433  // Note that the result can actually have IsDontDelete() == true when we
4434  // e.g. have to fall back to the slow case while adding a setter after
4435  // successfully reusing a map transition for a getter. Nevertheless, this is
4436  // OK, because the assertion only holds for the whole addition of both
4437  // accessors, not for the addition of each part. See first comment in
4438  // DefinePropertyAccessor below.
4439  Object* obj = result.GetCallbackObject();
4440  if (obj->IsAccessorPair()) {
4441  return AccessorPair::cast(obj)->Copy();
4442  }
4443  }
4444  return GetHeap()->AllocateAccessorPair();
4445 }
4446 
4447 
4448 MaybeObject* JSObject::DefinePropertyAccessor(String* name,
4449  Object* getter,
4450  Object* setter,
4451  PropertyAttributes attributes) {
4452  // We could assert that the property is configurable here, but we would need
4453  // to do a lookup, which seems to be a bit of overkill.
4454  Heap* heap = GetHeap();
4455  bool only_attribute_changes = getter->IsNull() && setter->IsNull();
4456  if (HasFastProperties() && !only_attribute_changes) {
4457  MaybeObject* getterOk = heap->undefined_value();
4458  if (!getter->IsNull()) {
4459  getterOk = DefineFastAccessor(name, ACCESSOR_GETTER, getter, attributes);
4460  if (getterOk->IsFailure()) return getterOk;
4461  }
4462 
4463  MaybeObject* setterOk = heap->undefined_value();
4464  if (getterOk != heap->null_value() && !setter->IsNull()) {
4465  setterOk = DefineFastAccessor(name, ACCESSOR_SETTER, setter, attributes);
4466  if (setterOk->IsFailure()) return setterOk;
4467  }
4468 
4469  if (getterOk != heap->null_value() && setterOk != heap->null_value()) {
4470  return heap->undefined_value();
4471  }
4472  }
4473 
4474  AccessorPair* accessors;
4475  MaybeObject* maybe_accessors = CreateAccessorPairFor(name);
4476  if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4477 
4478  accessors->SetComponents(getter, setter);
4479  return SetPropertyCallback(name, accessors, attributes);
4480 }
4481 
4482 
4483 bool JSObject::CanSetCallback(String* name) {
4484  ASSERT(!IsAccessCheckNeeded() ||
4485  GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
4486 
4487  // Check if there is an API defined callback object which prohibits
4488  // callback overwriting in this object or its prototype chain.
4489  // This mechanism is needed for instance in a browser setting, where
4490  // certain accessors such as window.location should not be allowed
4491  // to be overwritten because allowing overwriting could potentially
4492  // cause security problems.
4493  LookupResult callback_result(GetIsolate());
4494  LookupCallbackProperty(name, &callback_result);
4495  if (callback_result.IsFound()) {
4496  Object* obj = callback_result.GetCallbackObject();
4497  if (obj->IsAccessorInfo() &&
4499  return false;
4500  }
4501  }
4502 
4503  return true;
4504 }
4505 
4506 
4507 MaybeObject* JSObject::SetElementCallback(uint32_t index,
4508  Object* structure,
4509  PropertyAttributes attributes) {
4510  PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
4511 
4512  // Normalize elements to make this operation simple.
4513  SeededNumberDictionary* dictionary;
4514  { MaybeObject* maybe_dictionary = NormalizeElements();
4515  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4516  }
4518 
4519  // Update the dictionary with the new CALLBACKS property.
4520  { MaybeObject* maybe_dictionary = dictionary->Set(index, structure, details);
4521  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4522  }
4523 
4524  dictionary->set_requires_slow_elements();
4525  // Update the dictionary backing store on the object.
4526  if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
4527  // Also delete any parameter alias.
4528  //
4529  // TODO(kmillikin): when deleting the last parameter alias we could
4530  // switch to a direct backing store without the parameter map. This
4531  // would allow GC of the context.
4532  FixedArray* parameter_map = FixedArray::cast(elements());
4533  if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
4534  parameter_map->set(index + 2, GetHeap()->the_hole_value());
4535  }
4536  parameter_map->set(1, dictionary);
4537  } else {
4538  set_elements(dictionary);
4539  }
4540 
4541  return GetHeap()->undefined_value();
4542 }
4543 
4544 
4545 MaybeObject* JSObject::SetPropertyCallback(String* name,
4546  Object* structure,
4547  PropertyAttributes attributes) {
4548  // Normalize object to make this operation simple.
4549  MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
4550  if (maybe_ok->IsFailure()) return maybe_ok;
4551 
4552  // For the global object allocate a new map to invalidate the global inline
4553  // caches which have a global property cell reference directly in the code.
4554  if (IsGlobalObject()) {
4555  Map* new_map;
4556  MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
4557  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4558  ASSERT(new_map->is_dictionary_map());
4559 
4560  set_map(new_map);
4561  // When running crankshaft, changing the map is not enough. We
4562  // need to deoptimize all functions that rely on this global
4563  // object.
4565  }
4566 
4567  // Update the dictionary with the new CALLBACKS property.
4568  PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
4569  maybe_ok = SetNormalizedProperty(name, structure, details);
4570  if (maybe_ok->IsFailure()) return maybe_ok;
4571 
4572  return GetHeap()->undefined_value();
4573 }
4574 
4575 
4577  Handle<String> name,
4578  Handle<Object> getter,
4579  Handle<Object> setter,
4580  PropertyAttributes attributes) {
4582  object->GetIsolate(),
4583  object->DefineAccessor(*name, *getter, *setter, attributes));
4584 }
4585 
4587  Object* getter,
4588  Object* setter,
4589  PropertyAttributes attributes) {
4590  Isolate* isolate = GetIsolate();
4591  // Check access rights if needed.
4592  if (IsAccessCheckNeeded() &&
4593  !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4594  isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4595  return isolate->heap()->undefined_value();
4596  }
4597 
4598  if (IsJSGlobalProxy()) {
4599  Object* proto = GetPrototype();
4600  if (proto->IsNull()) return this;
4601  ASSERT(proto->IsJSGlobalObject());
4602  return JSObject::cast(proto)->DefineAccessor(
4603  name, getter, setter, attributes);
4604  }
4605 
4606  // Make sure that the top context does not change when doing callbacks or
4607  // interceptor calls.
4608  AssertNoContextChange ncc;
4609 
4610  // Try to flatten before operating on the string.
4611  name->TryFlatten();
4612 
4613  if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
4614 
4615  uint32_t index = 0;
4616  return name->AsArrayIndex(&index) ?
4617  DefineElementAccessor(index, getter, setter, attributes) :
4618  DefinePropertyAccessor(name, getter, setter, attributes);
4619 }
4620 
4621 
4622 static MaybeObject* TryAccessorTransition(JSObject* self,
4623  Map* transitioned_map,
4624  int target_descriptor,
4625  AccessorComponent component,
4626  Object* accessor,
4627  PropertyAttributes attributes) {
4628  DescriptorArray* descs = transitioned_map->instance_descriptors();
4629  PropertyDetails details = descs->GetDetails(target_descriptor);
4630 
4631  // If the transition target was not callbacks, fall back to the slow case.
4632  if (details.type() != CALLBACKS) return self->GetHeap()->null_value();
4633  Object* descriptor = descs->GetCallbacksObject(target_descriptor);
4634  if (!descriptor->IsAccessorPair()) return self->GetHeap()->null_value();
4635 
4636  Object* target_accessor = AccessorPair::cast(descriptor)->get(component);
4637  PropertyAttributes target_attributes = details.attributes();
4638 
4639  // Reuse transition if adding same accessor with same attributes.
4640  if (target_accessor == accessor && target_attributes == attributes) {
4641  self->set_map(transitioned_map);
4642  return self;
4643  }
4644 
4645  // If either not the same accessor, or not the same attributes, fall back to
4646  // the slow case.
4647  return self->GetHeap()->null_value();
4648 }
4649 
4650 
4652  AccessorComponent component,
4653  Object* accessor,
4654  PropertyAttributes attributes) {
4655  ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined());
4656  LookupResult result(GetIsolate());
4657  LocalLookup(name, &result);
4658 
4659  if (result.IsFound()
4660  && !result.IsPropertyCallbacks()
4661  && !result.IsTransition()) return GetHeap()->null_value();
4662 
4663  // Return success if the same accessor with the same attributes already exist.
4664  AccessorPair* source_accessors = NULL;
4665  if (result.IsPropertyCallbacks()) {
4666  Object* callback_value = result.GetCallbackObject();
4667  if (callback_value->IsAccessorPair()) {
4668  source_accessors = AccessorPair::cast(callback_value);
4669  Object* entry = source_accessors->get(component);
4670  if (entry == accessor && result.GetAttributes() == attributes) {
4671  return this;
4672  }
4673  } else {
4674  return GetHeap()->null_value();
4675  }
4676 
4677  int descriptor_number = result.GetDescriptorIndex();
4678 
4679  map()->LookupTransition(this, name, &result);
4680 
4681  if (result.IsFound()) {
4682  Map* target = result.GetTransitionTarget();
4683  ASSERT(target->NumberOfOwnDescriptors() ==
4685  // This works since descriptors are sorted in order of addition.
4686  ASSERT(map()->instance_descriptors()->GetKey(descriptor_number) == name);
4687  return TryAccessorTransition(
4688  this, target, descriptor_number, component, accessor, attributes);
4689  }
4690  } else {
4691  // If not, lookup a transition.
4692  map()->LookupTransition(this, name, &result);
4693 
4694  // If there is a transition, try to follow it.
4695  if (result.IsFound()) {
4696  Map* target = result.GetTransitionTarget();
4697  int descriptor_number = target->LastAdded();
4698  ASSERT(target->instance_descriptors()->GetKey(descriptor_number) == name);
4699  return TryAccessorTransition(
4700  this, target, descriptor_number, component, accessor, attributes);
4701  }
4702  }
4703 
4704  // If there is no transition yet, add a transition to the a new accessor pair
4705  // containing the accessor.
4706  AccessorPair* accessors;
4707  MaybeObject* maybe_accessors;
4708 
4709  // Allocate a new pair if there were no source accessors. Otherwise, copy the
4710  // pair and modify the accessor.
4711  if (source_accessors != NULL) {
4712  maybe_accessors = source_accessors->Copy();
4713  } else {
4714  maybe_accessors = GetHeap()->AllocateAccessorPair();
4715  }
4716  if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4717  accessors->set(component, accessor);
4718 
4719  CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
4720 
4721  Map* new_map;
4722  MaybeObject* maybe_new_map =
4723  map()->CopyInsertDescriptor(&new_accessors_desc, INSERT_TRANSITION);
4724  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4725 
4726  set_map(new_map);
4727  return this;
4728 }
4729 
4730 
4732  Isolate* isolate = GetIsolate();
4733  String* name = String::cast(info->name());
4734  // Check access rights if needed.
4735  if (IsAccessCheckNeeded() &&
4736  !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4737  isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4738  return isolate->heap()->undefined_value();
4739  }
4740 
4741  if (IsJSGlobalProxy()) {
4742  Object* proto = GetPrototype();
4743  if (proto->IsNull()) return this;
4744  ASSERT(proto->IsJSGlobalObject());
4745  return JSObject::cast(proto)->DefineAccessor(info);
4746  }
4747 
4748  // Make sure that the top context does not change when doing callbacks or
4749  // interceptor calls.
4750  AssertNoContextChange ncc;
4751 
4752  // Try to flatten before operating on the string.
4753  name->TryFlatten();
4754 
4755  if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
4756 
4757  uint32_t index = 0;
4758  bool is_element = name->AsArrayIndex(&index);
4759 
4760  if (is_element) {
4761  if (IsJSArray()) return isolate->heap()->undefined_value();
4762 
4763  // Accessors overwrite previous callbacks (cf. with getters/setters).
4764  switch (GetElementsKind()) {
4765  case FAST_SMI_ELEMENTS:
4766  case FAST_ELEMENTS:
4767  case FAST_DOUBLE_ELEMENTS:
4769  case FAST_HOLEY_ELEMENTS:
4771  break;
4777  case EXTERNAL_INT_ELEMENTS:
4781  // Ignore getters and setters on pixel and external array
4782  // elements.
4783  return isolate->heap()->undefined_value();
4784  case DICTIONARY_ELEMENTS:
4785  break;
4787  UNIMPLEMENTED();
4788  break;
4789  }
4790 
4791  MaybeObject* maybe_ok =
4792  SetElementCallback(index, info, info->property_attributes());
4793  if (maybe_ok->IsFailure()) return maybe_ok;
4794  } else {
4795  // Lookup the name.
4796  LookupResult result(isolate);
4797  LocalLookup(name, &result);
4798  // ES5 forbids turning a property into an accessor if it's not
4799  // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
4800  if (result.IsFound() && (result.IsReadOnly() || result.IsDontDelete())) {
4801  return isolate->heap()->undefined_value();
4802  }
4803 
4804  MaybeObject* maybe_ok =
4805  SetPropertyCallback(name, info, info->property_attributes());
4806  if (maybe_ok->IsFailure()) return maybe_ok;
4807  }
4808 
4809  return this;
4810 }
4811 
4812 
4814  Heap* heap = GetHeap();
4815 
4816  // Make sure that the top context does not change when doing callbacks or
4817  // interceptor calls.
4818  AssertNoContextChange ncc;
4819 
4820  // Check access rights if needed.
4821  if (IsAccessCheckNeeded() &&
4822  !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) {
4824  return heap->undefined_value();
4825  }
4826 
4827  // Make the lookup and include prototypes.
4828  uint32_t index = 0;
4829  if (name->AsArrayIndex(&index)) {
4830  for (Object* obj = this;
4831  obj != heap->null_value();
4832  obj = JSReceiver::cast(obj)->GetPrototype()) {
4833  if (obj->IsJSObject() && JSObject::cast(obj)->HasDictionaryElements()) {
4834  JSObject* js_object = JSObject::cast(obj);
4835  SeededNumberDictionary* dictionary = js_object->element_dictionary();
4836  int entry = dictionary->FindEntry(index);
4837  if (entry != SeededNumberDictionary::kNotFound) {
4838  Object* element = dictionary->ValueAt(entry);
4839  if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
4840  element->IsAccessorPair()) {
4841  return AccessorPair::cast(element)->GetComponent(component);
4842  }
4843  }
4844  }
4845  }
4846  } else {
4847  for (Object* obj = this;
4848  obj != heap->null_value();
4849  obj = JSReceiver::cast(obj)->GetPrototype()) {
4850  LookupResult result(heap->isolate());
4851  JSReceiver::cast(obj)->LocalLookup(name, &result);
4852  if (result.IsFound()) {
4853  if (result.IsReadOnly()) return heap->undefined_value();
4854  if (result.IsPropertyCallbacks()) {
4855  Object* obj = result.GetCallbackObject();
4856  if (obj->IsAccessorPair()) {
4857  return AccessorPair::cast(obj)->GetComponent(component);
4858  }
4859  }
4860  }
4861  }
4862  }
4863  return heap->undefined_value();
4864 }
4865 
4866 
4868  if (HasFastProperties()) {
4869  int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
4870  DescriptorArray* descs = map()->instance_descriptors();
4871  for (int i = 0; i < number_of_own_descriptors; i++) {
4872  if (descs->GetType(i) == FIELD) {
4873  if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
4874  return descs->GetKey(i);
4875  }
4876  } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
4877  if (descs->GetConstantFunction(i) == value) {
4878  return descs->GetKey(i);
4879  }
4880  }
4881  }
4882  return GetHeap()->undefined_value();
4883  } else {
4884  return property_dictionary()->SlowReverseLookup(value);
4885  }
4886 }
4887 
4888 
4889 MaybeObject* Map::RawCopy(int instance_size) {
4890  Map* result;
4891  MaybeObject* maybe_result =
4892  GetHeap()->AllocateMap(instance_type(), instance_size);
4893  if (!maybe_result->To(&result)) return maybe_result;
4894 
4895  result->set_prototype(prototype());
4896  result->set_constructor(constructor());
4897  result->set_bit_field(bit_field());
4898  result->set_bit_field2(bit_field2());
4899  result->set_bit_field3(bit_field3());
4900  int new_bit_field3 = bit_field3();
4901  new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
4902  new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
4903  new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache);
4904  result->set_bit_field3(new_bit_field3);
4905  return result;
4906 }
4907 
4908 
4910  NormalizedMapSharingMode sharing) {
4911  int new_instance_size = instance_size();
4912  if (mode == CLEAR_INOBJECT_PROPERTIES) {
4913  new_instance_size -= inobject_properties() * kPointerSize;
4914  }
4915 
4916  Map* result;
4917  MaybeObject* maybe_result = RawCopy(new_instance_size);
4918  if (!maybe_result->To(&result)) return maybe_result;
4919 
4920  if (mode != CLEAR_INOBJECT_PROPERTIES) {
4921  result->set_inobject_properties(inobject_properties());
4922  }
4923 
4924  result->set_code_cache(code_cache());
4925  result->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
4926  result->set_dictionary_map(true);
4927 
4928 #ifdef VERIFY_HEAP
4929  if (FLAG_verify_heap && result->is_shared()) {
4930  result->SharedMapVerify();
4931  }
4932 #endif
4933 
4934  return result;
4935 }
4936 
4937 
4939  Map* result;
4940  MaybeObject* maybe_result = RawCopy(instance_size());
4941  if (!maybe_result->To(&result)) return maybe_result;
4942 
4943  // Please note instance_type and instance_size are set when allocated.
4944  result->set_inobject_properties(inobject_properties());
4945  result->set_unused_property_fields(unused_property_fields());
4946 
4947  result->set_pre_allocated_property_fields(pre_allocated_property_fields());
4948  result->set_is_shared(false);
4949  result->ClearCodeCache(GetHeap());
4950  return result;
4951 }
4952 
4953 
4954 MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors,
4955  Descriptor* descriptor) {
4956  // Sanity check. This path is only to be taken if the map owns its descriptor
4957  // array, implying that its NumberOfOwnDescriptors equals the number of
4958  // descriptors in the descriptor array.
4959  ASSERT(NumberOfOwnDescriptors() ==
4960  instance_descriptors()->number_of_descriptors());
4961  Map* result;
4962  MaybeObject* maybe_result = CopyDropDescriptors();
4963  if (!maybe_result->To(&result)) return maybe_result;
4964 
4965  String* name = descriptor->GetKey();
4966 
4967  TransitionArray* transitions;
4968  MaybeObject* maybe_transitions =
4969  AddTransition(name, result, SIMPLE_TRANSITION);
4970  if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4971 
4972  int old_size = descriptors->number_of_descriptors();
4973 
4974  DescriptorArray* new_descriptors;
4975 
4976  if (descriptors->NumberOfSlackDescriptors() > 0) {
4977  new_descriptors = descriptors;
4978  new_descriptors->Append(descriptor);
4979  } else {
4980  // Descriptor arrays grow by 50%.
4981  MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
4982  old_size, old_size < 4 ? 1 : old_size / 2);
4983  if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
4984 
4985  DescriptorArray::WhitenessWitness witness(new_descriptors);
4986 
4987  // Copy the descriptors, inserting a descriptor.
4988  for (int i = 0; i < old_size; ++i) {
4989  new_descriptors->CopyFrom(i, descriptors, i, witness);
4990  }
4991 
4992  new_descriptors->Append(descriptor, witness);
4993 
4994  if (old_size > 0) {
4995  // If the source descriptors had an enum cache we copy it. This ensures
4996  // that the maps to which we push the new descriptor array back can rely
4997  // on a cache always being available once it is set. If the map has more
4998  // enumerated descriptors than available in the original cache, the cache
4999  // will be lazily replaced by the extended cache when needed.
5000  if (descriptors->HasEnumCache()) {
5001  new_descriptors->CopyEnumCacheFrom(descriptors);
5002  }
5003 
5004  Map* map;
5005  // Replace descriptors by new_descriptors in all maps that share it.
5006  for (Object* current = GetBackPointer();
5007  !current->IsUndefined();
5008  current = map->GetBackPointer()) {
5009  map = Map::cast(current);
5010  if (map->instance_descriptors() != descriptors) break;
5011  map->set_instance_descriptors(new_descriptors);
5012  }
5013 
5014  set_instance_descriptors(new_descriptors);
5015  }
5016  }
5017 
5018  result->SetBackPointer(this);
5019  result->InitializeDescriptors(new_descriptors);
5020  ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1);
5021 
5022  set_transitions(transitions);
5023  set_owns_descriptors(false);
5024 
5025  return result;
5026 }
5027 
5028 
5030  String* name,
5032  int descriptor_index) {
5033  ASSERT(descriptors->IsSortedNoDuplicates());
5034 
5035  Map* result;
5036  MaybeObject* maybe_result = CopyDropDescriptors();
5037  if (!maybe_result->To(&result)) return maybe_result;
5038 
5039  result->InitializeDescriptors(descriptors);
5040 
5041  if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
5042  TransitionArray* transitions;
5043  SimpleTransitionFlag simple_flag =
5044  (descriptor_index == descriptors->number_of_descriptors() - 1)
5046  : FULL_TRANSITION;
5047  MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
5048  if (!maybe_transitions->To(&transitions)) return maybe_transitions;
5049 
5050  set_transitions(transitions);
5051  result->SetBackPointer(this);
5052  }
5053 
5054  return result;
5055 }
5056 
5057 
5059  if (flag == INSERT_TRANSITION) {
5060  ASSERT(!HasElementsTransition() ||
5061  ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
5063  elements_transition_map()->elements_kind())) &&
5064  (kind == DICTIONARY_ELEMENTS ||
5065  IsExternalArrayElementsKind(kind))));
5066  ASSERT(!IsFastElementsKind(kind) ||
5067  IsMoreGeneralElementsKindTransition(elements_kind(), kind));
5068  ASSERT(kind != elements_kind());
5069  }
5070 
5071  bool insert_transition =
5072  flag == INSERT_TRANSITION && !HasElementsTransition();
5073 
5074  if (insert_transition && owns_descriptors()) {
5075  // In case the map owned its own descriptors, share the descriptors and
5076  // transfer ownership to the new map.
5077  Map* new_map;
5078  MaybeObject* maybe_new_map = CopyDropDescriptors();
5079  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
5080 
5081  MaybeObject* added_elements = set_elements_transition_map(new_map);
5082  if (added_elements->IsFailure()) return added_elements;
5083 
5084  new_map->set_elements_kind(kind);
5085  new_map->InitializeDescriptors(instance_descriptors());
5086  new_map->SetBackPointer(this);
5087  set_owns_descriptors(false);
5088  return new_map;
5089  }
5090 
5091  // In case the map did not own its own descriptors, a split is forced by
5092  // copying the map; creating a new descriptor array cell.
5093  // Create a new free-floating map only if we are not allowed to store it.
5094  Map* new_map;
5095  MaybeObject* maybe_new_map = Copy();
5096  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
5097 
5098  new_map->set_elements_kind(kind);
5099 
5100  if (insert_transition) {
5101  MaybeObject* added_elements = set_elements_transition_map(new_map);
5102  if (added_elements->IsFailure()) return added_elements;
5103  new_map->SetBackPointer(this);
5104  }
5105 
5106  return new_map;
5107 }
5108 
5109 
5111  if (pre_allocated_property_fields() == 0) return CopyDropDescriptors();
5112 
5113  // If the map has pre-allocated properties always start out with a descriptor
5114  // array describing these properties.
5115  ASSERT(constructor()->IsJSFunction());
5116  JSFunction* ctor = JSFunction::cast(constructor());
5117  Map* map = ctor->initial_map();
5118  DescriptorArray* descriptors = map->instance_descriptors();
5119 
5120  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
5121  DescriptorArray* new_descriptors;
5122  MaybeObject* maybe_descriptors =
5123  descriptors->CopyUpTo(number_of_own_descriptors);
5124  if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5125 
5126  return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
5127 }
5128 
5129 
5130 MaybeObject* Map::Copy() {
5131  DescriptorArray* descriptors = instance_descriptors();
5132  DescriptorArray* new_descriptors;
5133  int number_of_own_descriptors = NumberOfOwnDescriptors();
5134  MaybeObject* maybe_descriptors =
5135  descriptors->CopyUpTo(number_of_own_descriptors);
5136  if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5137 
5138  return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
5139 }
5140 
5141 
5142 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
5143  TransitionFlag flag) {
5144  DescriptorArray* descriptors = instance_descriptors();
5145 
5146  // Ensure the key is a symbol.
5147  MaybeObject* maybe_failure = descriptor->KeyToSymbol();
5148  if (maybe_failure->IsFailure()) return maybe_failure;
5149 
5150  int old_size = NumberOfOwnDescriptors();
5151  int new_size = old_size + 1;
5152  descriptor->SetEnumerationIndex(new_size);
5153 
5154  if (flag == INSERT_TRANSITION &&
5155  owns_descriptors() &&
5156  CanHaveMoreTransitions()) {
5157  return ShareDescriptor(descriptors, descriptor);
5158  }
5159 
5160  DescriptorArray* new_descriptors;
5161  MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size, 1);
5162  if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5163 
5164  DescriptorArray::WhitenessWitness witness(new_descriptors);
5165 
5166  // Copy the descriptors, inserting a descriptor.
5167  for (int i = 0; i < old_size; ++i) {
5168  new_descriptors->CopyFrom(i, descriptors, i, witness);
5169  }
5170 
5171  if (old_size != descriptors->number_of_descriptors()) {
5172  new_descriptors->SetNumberOfDescriptors(new_size);
5173  new_descriptors->Set(old_size, descriptor, witness);
5174  new_descriptors->Sort();
5175  } else {
5176  new_descriptors->Append(descriptor, witness);
5177  }
5178 
5179  String* key = descriptor->GetKey();
5180  int insertion_index = new_descriptors->number_of_descriptors() - 1;
5181 
5182  return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index);
5183 }
5184 
5185 
5186 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
5187  TransitionFlag flag) {
5188  DescriptorArray* old_descriptors = instance_descriptors();
5189 
5190  // Ensure the key is a symbol.
5191  MaybeObject* maybe_result = descriptor->KeyToSymbol();
5192  if (maybe_result->IsFailure()) return maybe_result;
5193 
5194  // We replace the key if it is already present.
5195  int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this);
5196  if (index != DescriptorArray::kNotFound) {
5197  return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag);
5198  }
5199  return CopyAddDescriptor(descriptor, flag);
5200 }
5201 
5202 
5203 MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) {
5204  if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
5205 
5206  int size = enumeration_index;
5207 
5208  DescriptorArray* descriptors;
5209  MaybeObject* maybe_descriptors = Allocate(size);
5210  if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
5211  DescriptorArray::WhitenessWitness witness(descriptors);
5212 
5213  for (int i = 0; i < size; ++i) {
5214  descriptors->CopyFrom(i, this, i, witness);
5215  }
5216 
5217  if (number_of_descriptors() != enumeration_index) descriptors->Sort();
5218 
5219  return descriptors;
5220 }
5221 
5222 
5224  Descriptor* descriptor,
5225  int insertion_index,
5226  TransitionFlag flag) {
5227  // Ensure the key is a symbol.
5228  MaybeObject* maybe_failure = descriptor->KeyToSymbol();
5229  if (maybe_failure->IsFailure()) return maybe_failure;
5230 
5231  String* key = descriptor->GetKey();
5232  ASSERT(key == descriptors->GetKey(insertion_index));
5233 
5234  int new_size = NumberOfOwnDescriptors();
5235  ASSERT(0 <= insertion_index && insertion_index < new_size);
5236 
5237  PropertyDetails details = descriptors->GetDetails(insertion_index);
5238  ASSERT_LE(details.descriptor_index(), new_size);
5239  descriptor->SetEnumerationIndex(details.descriptor_index());
5240 
5241  DescriptorArray* new_descriptors;
5242  MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size);
5243  if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5244  DescriptorArray::WhitenessWitness witness(new_descriptors);
5245 
5246  for (int i = 0; i < new_size; ++i) {
5247  if (i == insertion_index) {
5248  new_descriptors->Set(i, descriptor, witness);
5249  } else {
5250  new_descriptors->CopyFrom(i, descriptors, i, witness);
5251  }
5252  }
5253 
5254  // Re-sort if descriptors were removed.
5255  if (new_size != descriptors->length()) new_descriptors->Sort();
5256 
5257  return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index);
5258 }
5259 
5260 
5262  Handle<String> name,
5263  Handle<Code> code) {
5264  Isolate* isolate = map->GetIsolate();
5265  CALL_HEAP_FUNCTION_VOID(isolate,
5266  map->UpdateCodeCache(*name, *code));
5267 }
5268 
5269 
5270 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) {
5271  ASSERT(!is_shared() || code->allowed_in_shared_map_code_cache());
5272 
5273  // Allocate the code cache if not present.
5274  if (code_cache()->IsFixedArray()) {
5275  Object* result;
5276  { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache();
5277  if (!maybe_result->ToObject(&result)) return maybe_result;
5278  }
5279  set_code_cache(result);
5280  }
5281 
5282  // Update the code cache.
5283  return CodeCache::cast(code_cache())->Update(name, code);
5284 }
5285 
5286 
5288  // Do a lookup if a code cache exists.
5289  if (!code_cache()->IsFixedArray()) {
5290  return CodeCache::cast(code_cache())->Lookup(name, flags);
5291  } else {
5292  return GetHeap()->undefined_value();
5293  }
5294 }
5295 
5296 
5298  // Get the internal index if a code cache exists.
5299  if (!code_cache()->IsFixedArray()) {
5300  return CodeCache::cast(code_cache())->GetIndex(name, code);
5301  }
5302  return -1;
5303 }
5304 
5305 
5306 void Map::RemoveFromCodeCache(String* name, Code* code, int index) {
5307  // No GC is supposed to happen between a call to IndexInCodeCache and
5308  // RemoveFromCodeCache so the code cache must be there.
5309  ASSERT(!code_cache()->IsFixedArray());
5310  CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
5311 }
5312 
5313 
5314 // An iterator over all map transitions in an descriptor array, reusing the map
5315 // field of the contens array while it is running.
5317  public:
5319  : transition_array_(transition_array) { }
5320 
5321  void Start() {
5322  ASSERT(!IsIterating());
5323  *TransitionArrayHeader() = Smi::FromInt(0);
5324  }
5325 
5326  bool IsIterating() {
5327  return (*TransitionArrayHeader())->IsSmi();
5328  }
5329 
5330  Map* Next() {
5331  ASSERT(IsIterating());
5332  int index = Smi::cast(*TransitionArrayHeader())->value();
5333  int number_of_transitions = transition_array_->number_of_transitions();
5334  while (index < number_of_transitions) {
5335  *TransitionArrayHeader() = Smi::FromInt(index + 1);
5336  return transition_array_->GetTarget(index);
5337  }
5338 
5339  if (index == number_of_transitions &&
5340  transition_array_->HasElementsTransition()) {
5341  Map* elements_transition = transition_array_->elements_transition();
5342  *TransitionArrayHeader() = Smi::FromInt(index + 1);
5343  return elements_transition;
5344  }
5345  *TransitionArrayHeader() = transition_array_->GetHeap()->fixed_array_map();
5346  return NULL;
5347  }
5348 
5349  private:
5350  Object** TransitionArrayHeader() {
5351  return HeapObject::RawField(transition_array_, TransitionArray::kMapOffset);
5352  }
5353 
5354  TransitionArray* transition_array_;
5355 };
5356 
5357 
5358 // An iterator over all prototype transitions, reusing the map field of the
5359 // underlying array while it is running.
5361  public:
5363  : proto_trans_(proto_trans) { }
5364 
5365  void Start() {
5366  ASSERT(!IsIterating());
5367  *Header() = Smi::FromInt(0);
5368  }
5369 
5370  bool IsIterating() {
5371  return (*Header())->IsSmi();
5372  }
5373 
5374  Map* Next() {
5375  ASSERT(IsIterating());
5376  int transitionNumber = Smi::cast(*Header())->value();
5377  if (transitionNumber < NumberOfTransitions()) {
5378  *Header() = Smi::FromInt(transitionNumber + 1);
5379  return GetTransition(transitionNumber);
5380  }
5381  *Header() = proto_trans_->GetHeap()->fixed_array_map();
5382  return NULL;
5383  }
5384 
5385  private:
5386  Object** Header() {
5387  return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset);
5388  }
5389 
5390  int NumberOfTransitions() {
5391  FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
5392  Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
5393  return Smi::cast(num)->value();
5394  }
5395 
5396  Map* GetTransition(int transitionNumber) {
5397  FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
5398  return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
5399  }
5400 
5401  int IndexFor(int transitionNumber) {
5404  transitionNumber * Map::kProtoTransitionElementsPerEntry;
5405  }
5406 
5407  HeapObject* proto_trans_;
5408 };
5409 
5410 
5411 // To traverse the transition tree iteratively, we have to store two kinds of
5412 // information in a map: The parent map in the traversal and which children of a
5413 // node have already been visited. To do this without additional memory, we
5414 // temporarily reuse two maps with known values:
5415 //
5416 // (1) The map of the map temporarily holds the parent, and is restored to the
5417 // meta map afterwards.
5418 //
5419 // (2) The info which children have already been visited depends on which part
5420 // of the map we currently iterate:
5421 //
5422 // (a) If we currently follow normal map transitions, we temporarily store
5423 // the current index in the map of the FixedArray of the desciptor
5424 // array's contents, and restore it to the fixed array map afterwards.
5425 // Note that a single descriptor can have 0, 1, or 2 transitions.
5426 //
5427 // (b) If we currently follow prototype transitions, we temporarily store
5428 // the current index in the map of the FixedArray holding the prototype
5429 // transitions, and restore it to the fixed array map afterwards.
5430 //
5431 // Note that the child iterator is just a concatenation of two iterators: One
5432 // iterating over map transitions and one iterating over prototype transisitons.
5433 class TraversableMap : public Map {
5434  public:
5435  // Record the parent in the traversal within this map. Note that this destroys
5436  // this map's map!
5438 
5439  // Reset the current map's map, returning the parent previously stored in it.
5441  TraversableMap* old_parent = static_cast<TraversableMap*>(map());
5442  set_map_no_write_barrier(GetHeap()->meta_map());
5443  return old_parent;
5444  }
5445 
5446  // Start iterating over this map's children, possibly destroying a FixedArray
5447  // map (see explanation above).
5449  if (HasTransitionArray()) {
5450  if (HasPrototypeTransitions()) {
5451  IntrusivePrototypeTransitionIterator(GetPrototypeTransitions()).Start();
5452  }
5453 
5454  IntrusiveMapTransitionIterator(transitions()).Start();
5455  }
5456  }
5457 
5458  // If we have an unvisited child map, return that one and advance. If we have
5459  // none, return NULL and reset any destroyed FixedArray maps.
5461  TransitionArray* transition_array = unchecked_transition_array();
5462  if (!transition_array->map()->IsSmi() &&
5463  !transition_array->IsTransitionArray()) {
5464  return NULL;
5465  }
5466 
5467  if (transition_array->HasPrototypeTransitions()) {
5468  HeapObject* proto_transitions =
5469  transition_array->UncheckedPrototypeTransitions();
5470  IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions);
5471  if (proto_iterator.IsIterating()) {
5472  Map* next = proto_iterator.Next();
5473  if (next != NULL) return static_cast<TraversableMap*>(next);
5474  }
5475  }
5476 
5477  IntrusiveMapTransitionIterator transition_iterator(transition_array);
5478  if (transition_iterator.IsIterating()) {
5479  Map* next = transition_iterator.Next();
5480  if (next != NULL) return static_cast<TraversableMap*>(next);
5481  }
5482 
5483  return NULL;
5484  }
5485 };
5486 
5487 
5488 // Traverse the transition tree in postorder without using the C++ stack by
5489 // doing pointer reversal.
5490 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
5491  TraversableMap* current = static_cast<TraversableMap*>(this);
5492  current->ChildIteratorStart();
5493  while (true) {
5494  TraversableMap* child = current->ChildIteratorNext();
5495  if (child != NULL) {
5496  child->ChildIteratorStart();
5497  child->SetParent(current);
5498  current = child;
5499  } else {
5500  TraversableMap* parent = current->GetAndResetParent();
5501  callback(current, data);
5502  if (current == this) break;
5503  current = parent;
5504  }
5505  }
5506 }
5507 
5508 
5509 MaybeObject* CodeCache::Update(String* name, Code* code) {
5510  // The number of monomorphic stubs for normal load/store/call IC's can grow to
5511  // a large number and therefore they need to go into a hash table. They are
5512  // used to load global properties from cells.
5513  if (code->type() == Code::NORMAL) {
5514  // Make sure that a hash table is allocated for the normal load code cache.
5515  if (normal_type_cache()->IsUndefined()) {
5516  Object* result;
5517  { MaybeObject* maybe_result =
5519  if (!maybe_result->ToObject(&result)) return maybe_result;
5520  }
5521  set_normal_type_cache(result);
5522  }
5523  return UpdateNormalTypeCache(name, code);
5524  } else {
5525  ASSERT(default_cache()->IsFixedArray());
5526  return UpdateDefaultCache(name, code);
5527  }
5528 }
5529 
5530 
5531 MaybeObject* CodeCache::UpdateDefaultCache(String* name, Code* code) {
5532  // When updating the default code cache we disregard the type encoded in the
5533  // flags. This allows call constant stubs to overwrite call field
5534  // stubs, etc.
5536 
5537  // First check whether we can update existing code cache without
5538  // extending it.
5539  FixedArray* cache = default_cache();
5540  int length = cache->length();
5541  int deleted_index = -1;
5542  for (int i = 0; i < length; i += kCodeCacheEntrySize) {
5543  Object* key = cache->get(i);
5544  if (key->IsNull()) {
5545  if (deleted_index < 0) deleted_index = i;
5546  continue;
5547  }
5548  if (key->IsUndefined()) {
5549  if (deleted_index >= 0) i = deleted_index;
5550  cache->set(i + kCodeCacheEntryNameOffset, name);
5551  cache->set(i + kCodeCacheEntryCodeOffset, code);
5552  return this;
5553  }
5554  if (name->Equals(String::cast(key))) {
5555  Code::Flags found =
5556  Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
5557  if (Code::RemoveTypeFromFlags(found) == flags) {
5558  cache->set(i + kCodeCacheEntryCodeOffset, code);
5559  return this;
5560  }
5561  }
5562  }
5563 
5564  // Reached the end of the code cache. If there were deleted
5565  // elements, reuse the space for the first of them.
5566  if (deleted_index >= 0) {
5567  cache->set(deleted_index + kCodeCacheEntryNameOffset, name);
5568  cache->set(deleted_index + kCodeCacheEntryCodeOffset, code);
5569  return this;
5570  }
5571 
5572  // Extend the code cache with some new entries (at least one). Must be a
5573  // multiple of the entry size.
5574  int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
5575  new_length = new_length - new_length % kCodeCacheEntrySize;
5576  ASSERT((new_length % kCodeCacheEntrySize) == 0);
5577  Object* result;
5578  { MaybeObject* maybe_result = cache->CopySize(new_length);
5579  if (!maybe_result->ToObject(&result)) return maybe_result;
5580  }
5581 
5582  // Add the (name, code) pair to the new cache.
5583  cache = FixedArray::cast(result);
5584  cache->set(length + kCodeCacheEntryNameOffset, name);
5585  cache->set(length + kCodeCacheEntryCodeOffset, code);
5586  set_default_cache(cache);
5587  return this;
5588 }
5589 
5590 
5591 MaybeObject* CodeCache::UpdateNormalTypeCache(String* name, Code* code) {
5592  // Adding a new entry can cause a new cache to be allocated.
5593  CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5594  Object* new_cache;
5595  { MaybeObject* maybe_new_cache = cache->Put(name, code);
5596  if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
5597  }
5598  set_normal_type_cache(new_cache);
5599  return this;
5600 }
5601 
5602 
5604  if (Code::ExtractTypeFromFlags(flags) == Code::NORMAL) {
5605  return LookupNormalTypeCache(name, flags);
5606  } else {
5607  return LookupDefaultCache(name, flags);
5608  }
5609 }
5610 
5611 
5612 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) {
5613  FixedArray* cache = default_cache();
5614  int length = cache->length();
5615  for (int i = 0; i < length; i += kCodeCacheEntrySize) {
5616  Object* key = cache->get(i + kCodeCacheEntryNameOffset);
5617  // Skip deleted elements.
5618  if (key->IsNull()) continue;
5619  if (key->IsUndefined()) return key;
5620  if (name->Equals(String::cast(key))) {
5621  Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
5622  if (code->flags() == flags) {
5623  return code;
5624  }
5625  }
5626  }
5627  return GetHeap()->undefined_value();
5628 }
5629 
5630 
5631 Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) {
5632  if (!normal_type_cache()->IsUndefined()) {
5633  CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5634  return cache->Lookup(name, flags);
5635  } else {
5636  return GetHeap()->undefined_value();
5637  }
5638 }
5639 
5640 
5641 int CodeCache::GetIndex(Object* name, Code* code) {
5642  if (code->type() == Code::NORMAL) {
5643  if (normal_type_cache()->IsUndefined()) return -1;
5644  CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5645  return cache->GetIndex(String::cast(name), code->flags());
5646  }
5647 
5648  FixedArray* array = default_cache();
5649  int len = array->length();
5650  for (int i = 0; i < len; i += kCodeCacheEntrySize) {
5651  if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
5652  }
5653  return -1;
5654 }
5655 
5656 
5657 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
5658  if (code->type() == Code::NORMAL) {
5659  ASSERT(!normal_type_cache()->IsUndefined());
5660  CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5661  ASSERT(cache->GetIndex(String::cast(name), code->flags()) == index);
5662  cache->RemoveByIndex(index);
5663  } else {
5664  FixedArray* array = default_cache();
5665  ASSERT(array->length() >= index && array->get(index)->IsCode());
5666  // Use null instead of undefined for deleted elements to distinguish
5667  // deleted elements from unused elements. This distinction is used
5668  // when looking up in the cache and when updating the cache.
5669  ASSERT_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
5670  array->set_null(index - 1); // Name.
5671  array->set_null(index); // Code.
5672  }
5673 }
5674 
5675 
5676 // The key in the code cache hash table consists of the property name and the
5677 // code object. The actual match is on the name and the code flags. If a key
5678 // is created using the flags and not a code object it can only be used for
5679 // lookup not to create a new entry.
5681  public:
5683  : name_(name), flags_(flags), code_(NULL) { }
5684 
5686  : name_(name),
5687  flags_(code->flags()),
5688  code_(code) { }
5689 
5690 
5691  bool IsMatch(Object* other) {
5692  if (!other->IsFixedArray()) return false;
5693  FixedArray* pair = FixedArray::cast(other);
5694  String* name = String::cast(pair->get(0));
5695  Code::Flags flags = Code::cast(pair->get(1))->flags();
5696  if (flags != flags_) {
5697  return false;
5698  }
5699  return name_->Equals(name);
5700  }
5701 
5702  static uint32_t NameFlagsHashHelper(String* name, Code::Flags flags) {
5703  return name->Hash() ^ flags;
5704  }
5705 
5706  uint32_t Hash() { return NameFlagsHashHelper(name_, flags_); }
5707 
5708  uint32_t HashForObject(Object* obj) {
5709  FixedArray* pair = FixedArray::cast(obj);
5710  String* name = String::cast(pair->get(0));
5711  Code* code = Code::cast(pair->get(1));
5712  return NameFlagsHashHelper(name, code->flags());
5713  }
5714 
5715  MUST_USE_RESULT MaybeObject* AsObject() {
5716  ASSERT(code_ != NULL);
5717  Object* obj;
5718  { MaybeObject* maybe_obj = code_->GetHeap()->AllocateFixedArray(2);
5719  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5720  }
5721  FixedArray* pair = FixedArray::cast(obj);
5722  pair->set(0, name_);
5723  pair->set(1, code_);
5724  return pair;
5725  }
5726 
5727  private:
5728  String* name_;
5729  Code::Flags flags_;
5730  // TODO(jkummerow): We should be able to get by without this.
5731  Code* code_;
5732 };
5733 
5734 
5736  CodeCacheHashTableKey key(name, flags);
5737  int entry = FindEntry(&key);
5738  if (entry == kNotFound) return GetHeap()->undefined_value();
5739  return get(EntryToIndex(entry) + 1);
5740 }
5741 
5742 
5743 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) {
5744  CodeCacheHashTableKey key(name, code);
5745  Object* obj;
5746  { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
5747  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5748  }
5749 
5750  // Don't use |this|, as the table might have grown.
5751  CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj);
5752 
5753  int entry = cache->FindInsertionEntry(key.Hash());
5754  Object* k;
5755  { MaybeObject* maybe_k = key.AsObject();
5756  if (!maybe_k->ToObject(&k)) return maybe_k;
5757  }
5758 
5759  cache->set(EntryToIndex(entry), k);
5760  cache->set(EntryToIndex(entry) + 1, code);
5761  cache->ElementAdded();
5762  return cache;
5763 }
5764 
5765 
5767  CodeCacheHashTableKey key(name, flags);
5768  int entry = FindEntry(&key);
5769  return (entry == kNotFound) ? -1 : entry;
5770 }
5771 
5772 
5774  ASSERT(index >= 0);
5775  Heap* heap = GetHeap();
5776  set(EntryToIndex(index), heap->the_hole_value());
5777  set(EntryToIndex(index) + 1, heap->the_hole_value());
5778  ElementRemoved();
5779 }
5780 
5781 
5783  MapHandleList* maps,
5784  Code::Flags flags,
5785  Handle<Code> code) {
5786  Isolate* isolate = cache->GetIsolate();
5787  CALL_HEAP_FUNCTION_VOID(isolate, cache->Update(maps, flags, *code));
5788 }
5789 
5790 
5792  Code::Flags flags,
5793  Code* code) {
5794  // Initialize cache if necessary.
5795  if (cache()->IsUndefined()) {
5796  Object* result;
5797  { MaybeObject* maybe_result =
5800  if (!maybe_result->ToObject(&result)) return maybe_result;
5801  }
5802  set_cache(result);
5803  } else {
5804  // This entry shouldn't be contained in the cache yet.
5806  ->Lookup(maps, flags)->IsUndefined());
5807  }
5808  PolymorphicCodeCacheHashTable* hash_table =
5810  Object* new_cache;
5811  { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code);
5812  if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
5813  }
5814  set_cache(new_cache);
5815  return this;
5816 }
5817 
5818 
5820  Code::Flags flags) {
5821  if (!cache()->IsUndefined()) {
5822  PolymorphicCodeCacheHashTable* hash_table =
5824  return Handle<Object>(hash_table->Lookup(maps, flags));
5825  } else {
5826  return GetIsolate()->factory()->undefined_value();
5827  }
5828 }
5829 
5830 
5831 // Despite their name, object of this class are not stored in the actual
5832 // hash table; instead they're temporarily used for lookups. It is therefore
5833 // safe to have a weak (non-owning) pointer to a MapList as a member field.
5835  public:
5836  // Callers must ensure that |maps| outlives the newly constructed object.
5838  : maps_(maps),
5839  code_flags_(code_flags) {}
5840 
5841  bool IsMatch(Object* other) {
5842  MapHandleList other_maps(kDefaultListAllocationSize);
5843  int other_flags;
5844  FromObject(other, &other_flags, &other_maps);
5845  if (code_flags_ != other_flags) return false;
5846  if (maps_->length() != other_maps.length()) return false;
5847  // Compare just the hashes first because it's faster.
5848  int this_hash = MapsHashHelper(maps_, code_flags_);
5849  int other_hash = MapsHashHelper(&other_maps, other_flags);
5850  if (this_hash != other_hash) return false;
5851 
5852  // Full comparison: for each map in maps_, look for an equivalent map in
5853  // other_maps. This implementation is slow, but probably good enough for
5854  // now because the lists are short (<= 4 elements currently).
5855  for (int i = 0; i < maps_->length(); ++i) {
5856  bool match_found = false;
5857  for (int j = 0; j < other_maps.length(); ++j) {
5858  if (*(maps_->at(i)) == *(other_maps.at(j))) {
5859  match_found = true;
5860  break;
5861  }
5862  }
5863  if (!match_found) return false;
5864  }
5865  return true;
5866  }
5867 
5868  static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
5869  uint32_t hash = code_flags;
5870  for (int i = 0; i < maps->length(); ++i) {
5871  hash ^= maps->at(i)->Hash();
5872  }
5873  return hash;
5874  }
5875 
5876  uint32_t Hash() {
5877  return MapsHashHelper(maps_, code_flags_);
5878  }
5879 
5880  uint32_t HashForObject(Object* obj) {
5881  MapHandleList other_maps(kDefaultListAllocationSize);
5882  int other_flags;
5883  FromObject(obj, &other_flags, &other_maps);
5884  return MapsHashHelper(&other_maps, other_flags);
5885  }
5886 
5887  MUST_USE_RESULT MaybeObject* AsObject() {
5888  Object* obj;
5889  // The maps in |maps_| must be copied to a newly allocated FixedArray,
5890  // both because the referenced MapList is short-lived, and because C++
5891  // objects can't be stored in the heap anyway.
5892  { MaybeObject* maybe_obj =
5893  HEAP->AllocateUninitializedFixedArray(maps_->length() + 1);
5894  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5895  }
5896  FixedArray* list = FixedArray::cast(obj);
5897  list->set(0, Smi::FromInt(code_flags_));
5898  for (int i = 0; i < maps_->length(); ++i) {
5899  list->set(i + 1, *maps_->at(i));
5900  }
5901  return list;
5902  }
5903 
5904  private:
5905  static MapHandleList* FromObject(Object* obj,
5906  int* code_flags,
5907  MapHandleList* maps) {
5908  FixedArray* list = FixedArray::cast(obj);
5909  maps->Rewind(0);
5910  *code_flags = Smi::cast(list->get(0))->value();
5911  for (int i = 1; i < list->length(); ++i) {
5912  maps->Add(Handle<Map>(Map::cast(list->get(i))));
5913  }
5914  return maps;
5915  }
5916 
5917  MapHandleList* maps_; // weak.
5918  int code_flags_;
5919  static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
5920 };
5921 
5922 
5924  int code_flags) {
5925  PolymorphicCodeCacheHashTableKey key(maps, code_flags);
5926  int entry = FindEntry(&key);
5927  if (entry == kNotFound) return GetHeap()->undefined_value();
5928  return get(EntryToIndex(entry) + 1);
5929 }
5930 
5931 
5933  int code_flags,
5934  Code* code) {
5935  PolymorphicCodeCacheHashTableKey key(maps, code_flags);
5936  Object* obj;
5937  { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
5938  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5939  }
5941  reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj);
5942  int entry = cache->FindInsertionEntry(key.Hash());
5943  { MaybeObject* maybe_obj = key.AsObject();
5944  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5945  }
5946  cache->set(EntryToIndex(entry), obj);
5947  cache->set(EntryToIndex(entry) + 1, code);
5948  cache->ElementAdded();
5949  return cache;
5950 }
5951 
5952 
5954  ElementsAccessor* accessor = array->GetElementsAccessor();
5955  MaybeObject* maybe_result =
5956  accessor->AddElementsToFixedArray(array, array, this);
5957  FixedArray* result;
5958  if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
5959 #ifdef DEBUG
5961  for (int i = 0; i < result->length(); i++) {
5962  Object* current = result->get(i);
5963  ASSERT(current->IsNumber() || current->IsString());
5964  }
5965  }
5966 #endif
5967  return result;
5968 }
5969 
5970 
5971 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
5972  ElementsAccessor* accessor = ElementsAccessor::ForArray(other);
5973  MaybeObject* maybe_result =
5974  accessor->AddElementsToFixedArray(NULL, NULL, this, other);
5975  FixedArray* result;
5976  if (!maybe_result->To(&result)) return maybe_result;
5977 #ifdef DEBUG
5979  for (int i = 0; i < result->length(); i++) {
5980  Object* current = result->get(i);
5981  ASSERT(current->IsNumber() || current->IsString());
5982  }
5983  }
5984 #endif
5985  return result;
5986 }
5987 
5988 
5989 MaybeObject* FixedArray::CopySize(int new_length) {
5990  Heap* heap = GetHeap();
5991  if (new_length == 0) return heap->empty_fixed_array();
5992  Object* obj;
5993  { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length);
5994  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5995  }
5996  FixedArray* result = FixedArray::cast(obj);
5997  // Copy the content
5998  AssertNoAllocation no_gc;
5999  int len = length();
6000  if (new_length < len) len = new_length;
6001  // We are taking the map from the old fixed array so the map is sure to
6002  // be an immortal immutable object.
6003  result->set_map_no_write_barrier(map());
6004  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
6005  for (int i = 0; i < len; i++) {
6006  result->set(i, get(i), mode);
6007  }
6008  return result;
6009 }
6010 
6011 
6012 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
6013  AssertNoAllocation no_gc;
6014  WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
6015  for (int index = 0; index < len; index++) {
6016  dest->set(dest_pos+index, get(pos+index), mode);
6017  }
6018 }
6019 
6020 
6021 #ifdef DEBUG
6022 bool FixedArray::IsEqualTo(FixedArray* other) {
6023  if (length() != other->length()) return false;
6024  for (int i = 0 ; i < length(); ++i) {
6025  if (get(i) != other->get(i)) return false;
6026  }
6027  return true;
6028 }
6029 #endif
6030 
6031 
6032 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, int slack) {
6033  Heap* heap = Isolate::Current()->heap();
6034  // Do not use DescriptorArray::cast on incomplete object.
6035  int size = number_of_descriptors + slack;
6036  if (size == 0) return heap->empty_descriptor_array();
6037  FixedArray* result;
6038  // Allocate the array of keys.
6039  MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size));
6040  if (!maybe_array->To(&result)) return maybe_array;
6041 
6042  result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
6043  result->set(kEnumCacheIndex, Smi::FromInt(0));
6044  return result;
6045 }
6046 
6047 
6049  set(kEnumCacheIndex, Smi::FromInt(0));
6050 }
6051 
6052 
6054  FixedArray* new_cache,
6055  Object* new_index_cache) {
6056  ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
6057  ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
6058  ASSERT(!IsEmpty());
6059  ASSERT(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
6060  FixedArray::cast(bridge_storage)->
6061  set(kEnumCacheBridgeCacheIndex, new_cache);
6062  FixedArray::cast(bridge_storage)->
6063  set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
6064  set(kEnumCacheIndex, bridge_storage);
6065 }
6066 
6067 
6068 void DescriptorArray::CopyFrom(int dst_index,
6069  DescriptorArray* src,
6070  int src_index,
6071  const WhitenessWitness& witness) {
6072  Object* value = src->GetValue(src_index);
6073  PropertyDetails details = src->GetDetails(src_index);
6074  Descriptor desc(src->GetKey(src_index), value, details);
6075  Set(dst_index, &desc, witness);
6076 }
6077 
6078 
6079 // We need the whiteness witness since sort will reshuffle the entries in the
6080 // descriptor array. If the descriptor array were to be black, the shuffling
6081 // would move a slot that was already recorded as pointing into an evacuation
6082 // candidate. This would result in missing updates upon evacuation.
6084  // In-place heap sort.
6085  int len = number_of_descriptors();
6086  // Reset sorting since the descriptor array might contain invalid pointers.
6087  for (int i = 0; i < len; ++i) SetSortedKey(i, i);
6088  // Bottom-up max-heap construction.
6089  // Index of the last node with children
6090  const int max_parent_index = (len / 2) - 1;
6091  for (int i = max_parent_index; i >= 0; --i) {
6092  int parent_index = i;
6093  const uint32_t parent_hash = GetSortedKey(i)->Hash();
6094  while (parent_index <= max_parent_index) {
6095  int child_index = 2 * parent_index + 1;
6096  uint32_t child_hash = GetSortedKey(child_index)->Hash();
6097  if (child_index + 1 < len) {
6098  uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
6099  if (right_child_hash > child_hash) {
6100  child_index++;
6101  child_hash = right_child_hash;
6102  }
6103  }
6104  if (child_hash <= parent_hash) break;
6105  SwapSortedKeys(parent_index, child_index);
6106  // Now element at child_index could be < its children.
6107  parent_index = child_index; // parent_hash remains correct.
6108  }
6109  }
6110 
6111  // Extract elements and create sorted array.
6112  for (int i = len - 1; i > 0; --i) {
6113  // Put max element at the back of the array.
6114  SwapSortedKeys(0, i);
6115  // Shift down the new top element.
6116  int parent_index = 0;
6117  const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
6118  const int max_parent_index = (i / 2) - 1;
6119  while (parent_index <= max_parent_index) {
6120  int child_index = parent_index * 2 + 1;
6121  uint32_t child_hash = GetSortedKey(child_index)->Hash();
6122  if (child_index + 1 < i) {
6123  uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
6124  if (right_child_hash > child_hash) {
6125  child_index++;
6126  child_hash = right_child_hash;
6127  }
6128  }
6129  if (child_hash <= parent_hash) break;
6130  SwapSortedKeys(parent_index, child_index);
6131  parent_index = child_index;
6132  }
6133  }
6134  ASSERT(IsSortedNoDuplicates());
6135 }
6136 
6137 
6138 MaybeObject* AccessorPair::Copy() {
6139  Heap* heap = GetHeap();
6140  AccessorPair* copy;
6141  MaybeObject* maybe_copy = heap->AllocateAccessorPair();
6142  if (!maybe_copy->To(&copy)) return maybe_copy;
6143 
6144  copy->set_getter(getter());
6145  copy->set_setter(setter());
6146  return copy;
6147 }
6148 
6149 
6151  Object* accessor = get(component);
6152  return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
6153 }
6154 
6155 
6156 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count,
6157  PretenureFlag pretenure) {
6158  ASSERT(deopt_entry_count > 0);
6159  return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count),
6160  pretenure);
6161 }
6162 
6163 
6164 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points,
6165  PretenureFlag pretenure) {
6166  if (number_of_deopt_points == 0) return HEAP->empty_fixed_array();
6167  return HEAP->AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points),
6168  pretenure);
6169 }
6170 
6171 
6172 #ifdef DEBUG
6173 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
6174  if (IsEmpty()) return other->IsEmpty();
6175  if (other->IsEmpty()) return false;
6176  if (length() != other->length()) return false;
6177  for (int i = 0; i < length(); ++i) {
6178  if (get(i) != other->get(i)) return false;
6179  }
6180  return true;
6181 }
6182 #endif
6183 
6184 
6186  if (!Isolate::Current()->heap()->Contains(this)) return false;
6187  return true;
6188 }
6189 
6190 
6192  int length = this->length();
6193  StringShape shape(this);
6194  String* string = this;
6195  int offset = 0;
6196  if (shape.representation_tag() == kConsStringTag) {
6197  ConsString* cons = ConsString::cast(string);
6198  if (cons->second()->length() != 0) {
6199  return FlatContent();
6200  }
6201  string = cons->first();
6202  shape = StringShape(string);
6203  }
6204  if (shape.representation_tag() == kSlicedStringTag) {
6205  SlicedString* slice = SlicedString::cast(string);
6206  offset = slice->offset();
6207  string = slice->parent();
6208  shape = StringShape(string);
6209  ASSERT(shape.representation_tag() != kConsStringTag &&
6210  shape.representation_tag() != kSlicedStringTag);
6211  }
6212  if (shape.encoding_tag() == kAsciiStringTag) {
6213  const char* start;
6214  if (shape.representation_tag() == kSeqStringTag) {
6215  start = SeqAsciiString::cast(string)->GetChars();
6216  } else {
6217  start = ExternalAsciiString::cast(string)->GetChars();
6218  }
6219  return FlatContent(Vector<const char>(start + offset, length));
6220  } else {
6221  ASSERT(shape.encoding_tag() == kTwoByteStringTag);
6222  const uc16* start;
6223  if (shape.representation_tag() == kSeqStringTag) {
6224  start = SeqTwoByteString::cast(string)->GetChars();
6225  } else {
6226  start = ExternalTwoByteString::cast(string)->GetChars();
6227  }
6228  return FlatContent(Vector<const uc16>(start + offset, length));
6229  }
6230 }
6231 
6232 
6234  RobustnessFlag robust_flag,
6235  int offset,
6236  int length,
6237  int* length_return) {
6238  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
6239  return SmartArrayPointer<char>(NULL);
6240  }
6241  Heap* heap = GetHeap();
6242 
6243  // Negative length means the to the end of the string.
6244  if (length < 0) length = kMaxInt - offset;
6245 
6246  // Compute the size of the UTF-8 string. Start at the specified offset.
6249  buffer->Reset(offset, this);
6250  int character_position = offset;
6251  int utf8_bytes = 0;
6253  while (buffer->has_more() && character_position++ < offset + length) {
6254  uint16_t character = buffer->GetNext();
6255  utf8_bytes += unibrow::Utf8::Length(character, last);
6256  last = character;
6257  }
6258 
6259  if (length_return) {
6260  *length_return = utf8_bytes;
6261  }
6262 
6263  char* result = NewArray<char>(utf8_bytes + 1);
6264 
6265  // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
6266  buffer->Rewind();
6267  buffer->Seek(offset);
6268  character_position = offset;
6269  int utf8_byte_position = 0;
6271  while (buffer->has_more() && character_position++ < offset + length) {
6272  uint16_t character = buffer->GetNext();
6273  if (allow_nulls == DISALLOW_NULLS && character == 0) {
6274  character = ' ';
6275  }
6276  utf8_byte_position +=
6277  unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
6278  last = character;
6279  }
6280  result[utf8_byte_position] = 0;
6281  return SmartArrayPointer<char>(result);
6282 }
6283 
6284 
6286  RobustnessFlag robust_flag,
6287  int* length_return) {
6288  return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
6289 }
6290 
6291 
6293  return GetTwoByteData(0);
6294 }
6295 
6296 
6297 const uc16* String::GetTwoByteData(unsigned start) {
6298  ASSERT(!IsAsciiRepresentationUnderneath());
6299  switch (StringShape(this).representation_tag()) {
6300  case kSeqStringTag:
6301  return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
6302  case kExternalStringTag:
6303  return ExternalTwoByteString::cast(this)->
6304  ExternalTwoByteStringGetData(start);
6305  case kSlicedStringTag: {
6306  SlicedString* slice = SlicedString::cast(this);
6307  return slice->parent()->GetTwoByteData(start + slice->offset());
6308  }
6309  case kConsStringTag:
6310  UNREACHABLE();
6311  return NULL;
6312  }
6313  UNREACHABLE();
6314  return NULL;
6315 }
6316 
6317 
6319  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
6320  return SmartArrayPointer<uc16>();
6321  }
6322  Heap* heap = GetHeap();
6323 
6326  buffer->Reset(this);
6327 
6328  uc16* result = NewArray<uc16>(length() + 1);
6329 
6330  int i = 0;
6331  while (buffer->has_more()) {
6332  uint16_t character = buffer->GetNext();
6333  result[i++] = character;
6334  }
6335  result[i] = 0;
6336  return SmartArrayPointer<uc16>(result);
6337 }
6338 
6339 
6341  return reinterpret_cast<uc16*>(
6342  reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
6343 }
6344 
6345 
6347  unsigned* offset_ptr,
6348  unsigned max_chars) {
6349  unsigned chars_read = 0;
6350  unsigned offset = *offset_ptr;
6351  while (chars_read < max_chars) {
6352  uint16_t c = *reinterpret_cast<uint16_t*>(
6353  reinterpret_cast<char*>(this) -
6354  kHeapObjectTag + kHeaderSize + offset * kShortSize);
6355  if (c <= kMaxAsciiCharCode) {
6356  // Fast case for ASCII characters. Cursor is an input output argument.
6358  rbb->util_buffer,
6359  rbb->capacity,
6360  rbb->cursor)) {
6361  break;
6362  }
6363  } else {
6365  rbb->util_buffer,
6366  rbb->capacity,
6367  rbb->cursor)) {
6368  break;
6369  }
6370  }
6371  offset++;
6372  chars_read++;
6373  }
6374  *offset_ptr = offset;
6375  rbb->remaining += chars_read;
6376 }
6377 
6378 
6380  unsigned* remaining,
6381  unsigned* offset_ptr,
6382  unsigned max_chars) {
6383  const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) -
6384  kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize;
6385  *remaining = max_chars;
6386  *offset_ptr += max_chars;
6387  return b;
6388 }
6389 
6390 
6391 // This will iterate unless the block of string data spans two 'halves' of
6392 // a ConsString, in which case it will recurse. Since the block of string
6393 // data to be read has a maximum size this limits the maximum recursion
6394 // depth to something sane. Since C++ does not have tail call recursion
6395 // elimination, the iteration must be explicit. Since this is not an
6396 // -IntoBuffer method it can delegate to one of the efficient
6397 // *AsciiStringReadBlock routines.
6399  unsigned* offset_ptr,
6400  unsigned max_chars) {
6401  ConsString* current = this;
6402  unsigned offset = *offset_ptr;
6403  int offset_correction = 0;
6404 
6405  while (true) {
6406  String* left = current->first();
6407  unsigned left_length = (unsigned)left->length();
6408  if (left_length > offset &&
6409  (max_chars <= left_length - offset ||
6410  (rbb->capacity <= left_length - offset &&
6411  (max_chars = left_length - offset, true)))) { // comma operator!
6412  // Left hand side only - iterate unless we have reached the bottom of
6413  // the cons tree. The assignment on the left of the comma operator is
6414  // in order to make use of the fact that the -IntoBuffer routines can
6415  // produce at most 'capacity' characters. This enables us to postpone
6416  // the point where we switch to the -IntoBuffer routines (below) in order
6417  // to maximize the chances of delegating a big chunk of work to the
6418  // efficient *AsciiStringReadBlock routines.
6419  if (StringShape(left).IsCons()) {
6420  current = ConsString::cast(left);
6421  continue;
6422  } else {
6423  const unibrow::byte* answer =
6424  String::ReadBlock(left, rbb, &offset, max_chars);
6425  *offset_ptr = offset + offset_correction;
6426  return answer;
6427  }
6428  } else if (left_length <= offset) {
6429  // Right hand side only - iterate unless we have reached the bottom of
6430  // the cons tree.
6431  String* right = current->second();
6432  offset -= left_length;
6433  offset_correction += left_length;
6434  if (StringShape(right).IsCons()) {
6435  current = ConsString::cast(right);
6436  continue;
6437  } else {
6438  const unibrow::byte* answer =
6439  String::ReadBlock(right, rbb, &offset, max_chars);
6440  *offset_ptr = offset + offset_correction;
6441  return answer;
6442  }
6443  } else {
6444  // The block to be read spans two sides of the ConsString, so we call the
6445  // -IntoBuffer version, which will recurse. The -IntoBuffer methods
6446  // are able to assemble data from several part strings because they use
6447  // the util_buffer to store their data and never return direct pointers
6448  // to their storage. We don't try to read more than the buffer capacity
6449  // here or we can get too much recursion.
6450  ASSERT(rbb->remaining == 0);
6451  ASSERT(rbb->cursor == 0);
6453  rbb,
6454  &offset,
6455  max_chars > rbb->capacity ? rbb->capacity : max_chars);
6456  *offset_ptr = offset + offset_correction;
6457  return rbb->util_buffer;
6458  }
6459  }
6460 }
6461 
6462 
6464  unsigned* remaining,
6465  unsigned* offset_ptr,
6466  unsigned max_chars) {
6467  // Cast const char* to unibrow::byte* (signedness difference).
6468  const unibrow::byte* b =
6469  reinterpret_cast<const unibrow::byte*>(GetChars()) + *offset_ptr;
6470  *remaining = max_chars;
6471  *offset_ptr += max_chars;
6472  return b;
6473 }
6474 
6475 
6477  ReadBlockBuffer* rbb,
6478  unsigned* offset_ptr,
6479  unsigned max_chars) {
6480  unsigned chars_read = 0;
6481  unsigned offset = *offset_ptr;
6482  const uint16_t* data = GetChars();
6483  while (chars_read < max_chars) {
6484  uint16_t c = data[offset];
6485  if (c <= kMaxAsciiCharCode) {
6486  // Fast case for ASCII characters. Cursor is an input output argument.
6488  rbb->util_buffer,
6489  rbb->capacity,
6490  rbb->cursor))
6491  break;
6492  } else {
6494  rbb->util_buffer,
6495  rbb->capacity,
6496  rbb->cursor))
6497  break;
6498  }
6499  offset++;
6500  chars_read++;
6501  }
6502  *offset_ptr = offset;
6503  rbb->remaining += chars_read;
6504 }
6505 
6506 
6508  unsigned* offset_ptr,
6509  unsigned max_chars) {
6510  unsigned capacity = rbb->capacity - rbb->cursor;
6511  if (max_chars > capacity) max_chars = capacity;
6512  memcpy(rbb->util_buffer + rbb->cursor,
6513  reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize +
6514  *offset_ptr * kCharSize,
6515  max_chars);
6516  rbb->remaining += max_chars;
6517  *offset_ptr += max_chars;
6518  rbb->cursor += max_chars;
6519 }
6520 
6521 
6523  ReadBlockBuffer* rbb,
6524  unsigned* offset_ptr,
6525  unsigned max_chars) {
6526  unsigned capacity = rbb->capacity - rbb->cursor;
6527  if (max_chars > capacity) max_chars = capacity;
6528  memcpy(rbb->util_buffer + rbb->cursor, GetChars() + *offset_ptr, max_chars);
6529  rbb->remaining += max_chars;
6530  *offset_ptr += max_chars;
6531  rbb->cursor += max_chars;
6532 }
6533 
6534 
6535 // This method determines the type of string involved and then copies
6536 // a whole chunk of characters into a buffer, or returns a pointer to a buffer
6537 // where they can be found. The pointer is not necessarily valid across a GC
6538 // (see AsciiStringReadBlock).
6540  ReadBlockBuffer* rbb,
6541  unsigned* offset_ptr,
6542  unsigned max_chars) {
6543  ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
6544  if (max_chars == 0) {
6545  rbb->remaining = 0;
6546  return NULL;
6547  }
6548  switch (StringShape(input).representation_tag()) {
6549  case kSeqStringTag:
6550  if (input->IsAsciiRepresentation()) {
6551  SeqAsciiString* str = SeqAsciiString::cast(input);
6552  return str->SeqAsciiStringReadBlock(&rbb->remaining,
6553  offset_ptr,
6554  max_chars);
6555  } else {
6558  offset_ptr,
6559  max_chars);
6560  return rbb->util_buffer;
6561  }
6562  case kConsStringTag:
6563  return ConsString::cast(input)->ConsStringReadBlock(rbb,
6564  offset_ptr,
6565  max_chars);
6566  case kExternalStringTag:
6567  if (input->IsAsciiRepresentation()) {
6569  &rbb->remaining,
6570  offset_ptr,
6571  max_chars);
6572  } else {
6574  ExternalTwoByteStringReadBlockIntoBuffer(rbb,
6575  offset_ptr,
6576  max_chars);
6577  return rbb->util_buffer;
6578  }
6579  case kSlicedStringTag:
6580  return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
6581  offset_ptr,
6582  max_chars);
6583  default:
6584  break;
6585  }
6586 
6587  UNREACHABLE();
6588  return 0;
6589 }
6590 
6591 
6592 void Relocatable::PostGarbageCollectionProcessing() {
6593  Isolate* isolate = Isolate::Current();
6594  Relocatable* current = isolate->relocatable_top();
6595  while (current != NULL) {
6596  current->PostGarbageCollection();
6597  current = current->prev_;
6598  }
6599 }
6600 
6601 
6602 // Reserve space for statics needing saving and restoring.
6603 int Relocatable::ArchiveSpacePerThread() {
6604  return sizeof(Isolate::Current()->relocatable_top());
6605 }
6606 
6607 
6608 // Archive statics that are thread local.
6609 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
6610  *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
6611  isolate->set_relocatable_top(NULL);
6612  return to + ArchiveSpacePerThread();
6613 }
6614 
6615 
6616 // Restore statics that are thread local.
6617 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
6618  isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
6619  return from + ArchiveSpacePerThread();
6620 }
6621 
6622 
6623 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
6624  Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
6625  Iterate(v, top);
6626  return thread_storage + ArchiveSpacePerThread();
6627 }
6628 
6629 
6630 void Relocatable::Iterate(ObjectVisitor* v) {
6631  Isolate* isolate = Isolate::Current();
6632  Iterate(v, isolate->relocatable_top());
6633 }
6634 
6635 
6636 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
6637  Relocatable* current = top;
6638  while (current != NULL) {
6639  current->IterateInstance(v);
6640  current = current->prev_;
6641  }
6642 }
6643 
6644 
6646  : Relocatable(isolate),
6647  str_(str.location()),
6648  length_(str->length()) {
6650 }
6651 
6652 
6654  : Relocatable(isolate),
6655  str_(0),
6656  is_ascii_(true),
6657  length_(input.length()),
6658  start_(input.start()) { }
6659 
6660 
6662  if (str_ == NULL) return;
6663  Handle<String> str(str_);
6664  ASSERT(str->IsFlat());
6665  String::FlatContent content = str->GetFlatContent();
6666  ASSERT(content.IsFlat());
6667  is_ascii_ = content.IsAscii();
6668  if (is_ascii_) {
6669  start_ = content.ToAsciiVector().start();
6670  } else {
6671  start_ = content.ToUC16Vector().start();
6672  }
6673 }
6674 
6675 
6676 void StringInputBuffer::Seek(unsigned pos) {
6677  Reset(pos, input_);
6678 }
6679 
6680 
6681 void SafeStringInputBuffer::Seek(unsigned pos) {
6682  Reset(pos, input_);
6683 }
6684 
6685 
6686 // This method determines the type of string involved and then copies
6687 // a whole chunk of characters into a buffer. It can be used with strings
6688 // that have been glued together to form a ConsString and which must cooperate
6689 // to fill up a buffer.
6691  ReadBlockBuffer* rbb,
6692  unsigned* offset_ptr,
6693  unsigned max_chars) {
6694  ASSERT(*offset_ptr <= (unsigned)input->length());
6695  if (max_chars == 0) return;
6696 
6697  switch (StringShape(input).representation_tag()) {
6698  case kSeqStringTag:
6699  if (input->IsAsciiRepresentation()) {
6701  offset_ptr,
6702  max_chars);
6703  return;
6704  } else {
6706  offset_ptr,
6707  max_chars);
6708  return;
6709  }
6710  case kConsStringTag:
6712  offset_ptr,
6713  max_chars);
6714  return;
6715  case kExternalStringTag:
6716  if (input->IsAsciiRepresentation()) {
6717  ExternalAsciiString::cast(input)->
6718  ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
6719  } else {
6721  ExternalTwoByteStringReadBlockIntoBuffer(rbb,
6722  offset_ptr,
6723  max_chars);
6724  }
6725  return;
6726  case kSlicedStringTag:
6728  offset_ptr,
6729  max_chars);
6730  return;
6731  default:
6732  break;
6733  }
6734 
6735  UNREACHABLE();
6736  return;
6737 }
6738 
6739 
6741  unibrow::byte* util_buffer,
6742  unsigned capacity,
6743  unsigned* remaining,
6744  unsigned* offset_ptr) {
6745  ASSERT(*offset_ptr <= (unsigned)input->length());
6746  unsigned chars = input->length() - *offset_ptr;
6747  ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
6748  const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
6749  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
6750  *remaining = rbb.remaining;
6751  return answer;
6752 }
6753 
6754 
6756  unibrow::byte* util_buffer,
6757  unsigned capacity,
6758  unsigned* remaining,
6759  unsigned* offset_ptr) {
6760  Handle<String> input(raw_input);
6761  ASSERT(*offset_ptr <= (unsigned)input->length());
6762  unsigned chars = input->length() - *offset_ptr;
6763  if (chars > capacity) chars = capacity;
6764  ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
6765  ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
6766  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
6767  *remaining = rbb.remaining;
6768  return rbb.util_buffer;
6769 }
6770 
6771 
6772 // This will iterate unless the block of string data spans two 'halves' of
6773 // a ConsString, in which case it will recurse. Since the block of string
6774 // data to be read has a maximum size this limits the maximum recursion
6775 // depth to something sane. Since C++ does not have tail call recursion
6776 // elimination, the iteration must be explicit.
6778  unsigned* offset_ptr,
6779  unsigned max_chars) {
6780  ConsString* current = this;
6781  unsigned offset = *offset_ptr;
6782  int offset_correction = 0;
6783 
6784  while (true) {
6785  String* left = current->first();
6786  unsigned left_length = (unsigned)left->length();
6787  if (left_length > offset &&
6788  max_chars <= left_length - offset) {
6789  // Left hand side only - iterate unless we have reached the bottom of
6790  // the cons tree.
6791  if (StringShape(left).IsCons()) {
6792  current = ConsString::cast(left);
6793  continue;
6794  } else {
6795  String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
6796  *offset_ptr = offset + offset_correction;
6797  return;
6798  }
6799  } else if (left_length <= offset) {
6800  // Right hand side only - iterate unless we have reached the bottom of
6801  // the cons tree.
6802  offset -= left_length;
6803  offset_correction += left_length;
6804  String* right = current->second();
6805  if (StringShape(right).IsCons()) {
6806  current = ConsString::cast(right);
6807  continue;
6808  } else {
6809  String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
6810  *offset_ptr = offset + offset_correction;
6811  return;
6812  }
6813  } else {
6814  // The block to be read spans two sides of the ConsString, so we recurse.
6815  // First recurse on the left.
6816  max_chars -= left_length - offset;
6817  String::ReadBlockIntoBuffer(left, rbb, &offset, left_length - offset);
6818  // We may have reached the max or there may not have been enough space
6819  // in the buffer for the characters in the left hand side.
6820  if (offset == left_length) {
6821  // Recurse on the right.
6822  String* right = String::cast(current->second());
6823  offset -= left_length;
6824  offset_correction += left_length;
6825  String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
6826  }
6827  *offset_ptr = offset + offset_correction;
6828  return;
6829  }
6830  }
6831 }
6832 
6833 
6835  ASSERT(index >= 0 && index < this->length());
6836 
6837  // Check for a flattened cons string
6838  if (second()->length() == 0) {
6839  String* left = first();
6840  return left->Get(index);
6841  }
6842 
6843  String* string = String::cast(this);
6844 
6845  while (true) {
6846  if (StringShape(string).IsCons()) {
6847  ConsString* cons_string = ConsString::cast(string);
6848  String* left = cons_string->first();
6849  if (left->length() > index) {
6850  string = left;
6851  } else {
6852  index -= left->length();
6853  string = cons_string->second();
6854  }
6855  } else {
6856  return string->Get(index);
6857  }
6858  }
6859 
6860  UNREACHABLE();
6861  return 0;
6862 }
6863 
6864 
6866  return parent()->Get(offset() + index);
6867 }
6868 
6869 
6871  ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6872  unsigned offset = this->offset();
6873  *offset_ptr += offset;
6875  buffer, offset_ptr, chars);
6876  *offset_ptr -= offset;
6877  return answer;
6878 }
6879 
6880 
6882  ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6883  unsigned offset = this->offset();
6884  *offset_ptr += offset;
6886  buffer, offset_ptr, chars);
6887  *offset_ptr -= offset;
6888 }
6889 
6890 template <typename sinkchar>
6892  sinkchar* sink,
6893  int f,
6894  int t) {
6895  String* source = src;
6896  int from = f;
6897  int to = t;
6898  while (true) {
6899  ASSERT(0 <= from && from <= to && to <= source->length());
6900  switch (StringShape(source).full_representation_tag()) {
6902  CopyChars(sink,
6903  ExternalAsciiString::cast(source)->GetChars() + from,
6904  to - from);
6905  return;
6906  }
6908  const uc16* data =
6910  CopyChars(sink,
6911  data + from,
6912  to - from);
6913  return;
6914  }
6915  case kAsciiStringTag | kSeqStringTag: {
6916  CopyChars(sink,
6917  SeqAsciiString::cast(source)->GetChars() + from,
6918  to - from);
6919  return;
6920  }
6922  CopyChars(sink,
6923  SeqTwoByteString::cast(source)->GetChars() + from,
6924  to - from);
6925  return;
6926  }
6929  ConsString* cons_string = ConsString::cast(source);
6930  String* first = cons_string->first();
6931  int boundary = first->length();
6932  if (to - boundary >= boundary - from) {
6933  // Right hand side is longer. Recurse over left.
6934  if (from < boundary) {
6935  WriteToFlat(first, sink, from, boundary);
6936  sink += boundary - from;
6937  from = 0;
6938  } else {
6939  from -= boundary;
6940  }
6941  to -= boundary;
6942  source = cons_string->second();
6943  } else {
6944  // Left hand side is longer. Recurse over right.
6945  if (to > boundary) {
6946  String* second = cons_string->second();
6947  // When repeatedly appending to a string, we get a cons string that
6948  // is unbalanced to the left, a list, essentially. We inline the
6949  // common case of sequential ascii right child.
6950  if (to - boundary == 1) {
6951  sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
6952  } else if (second->IsSeqAsciiString()) {
6953  CopyChars(sink + boundary - from,
6954  SeqAsciiString::cast(second)->GetChars(),
6955  to - boundary);
6956  } else {
6957  WriteToFlat(second,
6958  sink + boundary - from,
6959  0,
6960  to - boundary);
6961  }
6962  to = boundary;
6963  }
6964  source = first;
6965  }
6966  break;
6967  }
6970  SlicedString* slice = SlicedString::cast(source);
6971  unsigned offset = slice->offset();
6972  WriteToFlat(slice->parent(), sink, from + offset, to + offset);
6973  return;
6974  }
6975  }
6976  }
6977 }
6978 
6979 
6980 template <typename IteratorA, typename IteratorB>
6981 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
6982  // General slow case check. We know that the ia and ib iterators
6983  // have the same length.
6984  while (ia->has_more()) {
6985  uint32_t ca = ia->GetNext();
6986  uint32_t cb = ib->GetNext();
6989  if (ca != cb)
6990  return false;
6991  }
6992  return true;
6993 }
6994 
6995 
6996 // Compares the contents of two strings by reading and comparing
6997 // int-sized blocks of characters.
6998 template <typename Char>
6999 static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
7000  int length = a.length();
7001  ASSERT_EQ(length, b.length());
7002  const Char* pa = a.start();
7003  const Char* pb = b.start();
7004  int i = 0;
7005 #ifndef V8_HOST_CAN_READ_UNALIGNED
7006  // If this architecture isn't comfortable reading unaligned ints
7007  // then we have to check that the strings are aligned before
7008  // comparing them blockwise.
7009  const int kAlignmentMask = sizeof(uint32_t) - 1; // NOLINT
7010  uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
7011  uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
7012  if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
7013 #endif
7014  const int kStepSize = sizeof(int) / sizeof(Char); // NOLINT
7015  int endpoint = length - kStepSize;
7016  // Compare blocks until we reach near the end of the string.
7017  for (; i <= endpoint; i += kStepSize) {
7018  uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i);
7019  uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i);
7020  if (wa != wb) {
7021  return false;
7022  }
7023  }
7024 #ifndef V8_HOST_CAN_READ_UNALIGNED
7025  }
7026 #endif
7027  // Compare the remaining characters that didn't fit into a block.
7028  for (; i < length; i++) {
7029  if (a[i] != b[i]) {
7030  return false;
7031  }
7032  }
7033  return true;
7034 }
7035 
7036 
7037 template <typename IteratorA>
7038 static inline bool CompareStringContentsPartial(Isolate* isolate,
7039  IteratorA* ia,
7040  String* b) {
7041  String::FlatContent content = b->GetFlatContent();
7042  if (content.IsFlat()) {
7043  if (content.IsAscii()) {
7044  VectorIterator<char> ib(content.ToAsciiVector());
7045  return CompareStringContents(ia, &ib);
7046  } else {
7047  VectorIterator<uc16> ib(content.ToUC16Vector());
7048  return CompareStringContents(ia, &ib);
7049  }
7050  } else {
7051  isolate->objects_string_compare_buffer_b()->Reset(0, b);
7052  return CompareStringContents(ia,
7053  isolate->objects_string_compare_buffer_b());
7054  }
7055 }
7056 
7057 
7058 bool String::SlowEquals(String* other) {
7059  // Fast check: negative check with lengths.
7060  int len = length();
7061  if (len != other->length()) return false;
7062  if (len == 0) return true;
7063 
7064  // Fast check: if hash code is computed for both strings
7065  // a fast negative check can be performed.
7066  if (HasHashCode() && other->HasHashCode()) {
7067 #ifdef DEBUG
7069  if (Hash() != other->Hash()) {
7070  bool found_difference = false;
7071  for (int i = 0; i < len; i++) {
7072  if (Get(i) != other->Get(i)) {
7073  found_difference = true;
7074  break;
7075  }
7076  }
7077  ASSERT(found_difference);
7078  }
7079  }
7080 #endif
7081  if (Hash() != other->Hash()) return false;
7082  }
7083 
7084  // We know the strings are both non-empty. Compare the first chars
7085  // before we try to flatten the strings.
7086  if (this->Get(0) != other->Get(0)) return false;
7087 
7088  String* lhs = this->TryFlattenGetString();
7089  String* rhs = other->TryFlattenGetString();
7090 
7091  if (StringShape(lhs).IsSequentialAscii() &&
7092  StringShape(rhs).IsSequentialAscii()) {
7093  const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
7094  const char* str2 = SeqAsciiString::cast(rhs)->GetChars();
7095  return CompareRawStringContents(Vector<const char>(str1, len),
7096  Vector<const char>(str2, len));
7097  }
7098 
7099  Isolate* isolate = GetIsolate();
7100  String::FlatContent lhs_content = lhs->GetFlatContent();
7101  String::FlatContent rhs_content = rhs->GetFlatContent();
7102  if (lhs_content.IsFlat()) {
7103  if (lhs_content.IsAscii()) {
7104  Vector<const char> vec1 = lhs_content.ToAsciiVector();
7105  if (rhs_content.IsFlat()) {
7106  if (rhs_content.IsAscii()) {
7107  Vector<const char> vec2 = rhs_content.ToAsciiVector();
7108  return CompareRawStringContents(vec1, vec2);
7109  } else {
7110  VectorIterator<char> buf1(vec1);
7111  VectorIterator<uc16> ib(rhs_content.ToUC16Vector());
7112  return CompareStringContents(&buf1, &ib);
7113  }
7114  } else {
7115  VectorIterator<char> buf1(vec1);
7116  isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
7117  return CompareStringContents(&buf1,
7118  isolate->objects_string_compare_buffer_b());
7119  }
7120  } else {
7121  Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
7122  if (rhs_content.IsFlat()) {
7123  if (rhs_content.IsAscii()) {
7124  VectorIterator<uc16> buf1(vec1);
7125  VectorIterator<char> ib(rhs_content.ToAsciiVector());
7126  return CompareStringContents(&buf1, &ib);
7127  } else {
7128  Vector<const uc16> vec2(rhs_content.ToUC16Vector());
7129  return CompareRawStringContents(vec1, vec2);
7130  }
7131  } else {
7132  VectorIterator<uc16> buf1(vec1);
7133  isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
7134  return CompareStringContents(&buf1,
7135  isolate->objects_string_compare_buffer_b());
7136  }
7137  }
7138  } else {
7139  isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
7140  return CompareStringContentsPartial(isolate,
7141  isolate->objects_string_compare_buffer_a(), rhs);
7142  }
7143 }
7144 
7145 
7147  if (StringShape(this).IsSymbol()) return false;
7148 
7149  Map* map = this->map();
7150  Heap* heap = GetHeap();
7151  if (map == heap->string_map()) {
7152  this->set_map(heap->undetectable_string_map());
7153  return true;
7154  } else if (map == heap->ascii_string_map()) {
7155  this->set_map(heap->undetectable_ascii_string_map());
7156  return true;
7157  }
7158  // Rest cannot be marked as undetectable
7159  return false;
7160 }
7161 
7162 
7164  Isolate* isolate = GetIsolate();
7165  int slen = length();
7167  decoder(isolate->unicode_cache()->utf8_decoder());
7168  decoder->Reset(str.start(), str.length());
7169  int i;
7170  for (i = 0; i < slen && decoder->has_more(); i++) {
7171  uint32_t r = decoder->GetNext();
7173  if (i > slen - 1) return false;
7174  if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
7175  if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
7176  } else {
7177  if (Get(i) != r) return false;
7178  }
7179  }
7180  return i == slen && !decoder->has_more();
7181 }
7182 
7183 
7185  int slen = length();
7186  if (str.length() != slen) return false;
7187  FlatContent content = GetFlatContent();
7188  if (content.IsAscii()) {
7189  return CompareChars(content.ToAsciiVector().start(),
7190  str.start(), slen) == 0;
7191  }
7192  for (int i = 0; i < slen; i++) {
7193  if (Get(i) != static_cast<uint16_t>(str[i])) return false;
7194  }
7195  return true;
7196 }
7197 
7198 
7200  int slen = length();
7201  if (str.length() != slen) return false;
7202  FlatContent content = GetFlatContent();
7203  if (content.IsTwoByte()) {
7204  return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
7205  }
7206  for (int i = 0; i < slen; i++) {
7207  if (Get(i) != str[i]) return false;
7208  }
7209  return true;
7210 }
7211 
7212 
7213 uint32_t String::ComputeAndSetHash() {
7214  // Should only be called if hash code has not yet been computed.
7215  ASSERT(!HasHashCode());
7216 
7217  const int len = length();
7218 
7219  // Compute the hash code.
7220  uint32_t field = 0;
7221  if (StringShape(this).IsSequentialAscii()) {
7222  field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(),
7223  len,
7224  GetHeap()->HashSeed());
7225  } else if (StringShape(this).IsSequentialTwoByte()) {
7226  field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(),
7227  len,
7228  GetHeap()->HashSeed());
7229  } else {
7230  StringInputBuffer buffer(this);
7231  field = ComputeHashField(&buffer, len, GetHeap()->HashSeed());
7232  }
7233 
7234  // Store the hash code in the object.
7235  set_hash_field(field);
7236 
7237  // Check the hash code is there.
7238  ASSERT(HasHashCode());
7239  uint32_t result = field >> kHashShift;
7240  ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
7241  return result;
7242 }
7243 
7244 
7246  uint32_t* index,
7247  int length) {
7248  if (length == 0 || length > kMaxArrayIndexSize) return false;
7249  uc32 ch = buffer->GetNext();
7250 
7251  // If the string begins with a '0' character, it must only consist
7252  // of it to be a legal array index.
7253  if (ch == '0') {
7254  *index = 0;
7255  return length == 1;
7256  }
7257 
7258  // Convert string to uint32 array index; character by character.
7259  int d = ch - '0';
7260  if (d < 0 || d > 9) return false;
7261  uint32_t result = d;
7262  while (buffer->has_more()) {
7263  d = buffer->GetNext() - '0';
7264  if (d < 0 || d > 9) return false;
7265  // Check that the new result is below the 32 bit limit.
7266  if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
7267  result = (result * 10) + d;
7268  }
7269 
7270  *index = result;
7271  return true;
7272 }
7273 
7274 
7275 bool String::SlowAsArrayIndex(uint32_t* index) {
7277  Hash(); // force computation of hash code
7278  uint32_t field = hash_field();
7279  if ((field & kIsNotArrayIndexMask) != 0) return false;
7280  // Isolate the array index form the full hash field.
7281  *index = (kArrayIndexHashMask & field) >> kHashShift;
7282  return true;
7283  } else {
7284  StringInputBuffer buffer(this);
7285  return ComputeArrayIndex(&buffer, index, length());
7286  }
7287 }
7288 
7289 
7290 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
7291  // For array indexes mix the length into the hash as an array index could
7292  // be zero.
7293  ASSERT(length > 0);
7297 
7298  value <<= String::kHashShift;
7299  value |= length << String::kArrayIndexHashLengthShift;
7300 
7301  ASSERT((value & String::kIsNotArrayIndexMask) == 0);
7303  (value & String::kContainsCachedArrayIndexMask) == 0);
7304  return value;
7305 }
7306 
7307 
7310  AddCharacter(lead);
7312  AddCharacter(trail);
7313 }
7314 
7315 
7318  AddCharacterNoIndex(lead);
7320  AddCharacterNoIndex(trail);
7321 }
7322 
7323 
7325  if (length_ <= String::kMaxHashCalcLength) {
7326  if (is_array_index()) {
7327  return MakeArrayIndexHash(array_index(), length_);
7328  }
7329  return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask;
7330  } else {
7331  return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
7332  }
7333 }
7334 
7335 
7337  int length,
7338  uint32_t seed) {
7339  StringHasher hasher(length, seed);
7340 
7341  // Very long strings have a trivial hash that doesn't inspect the
7342  // string contents.
7343  if (hasher.has_trivial_hash()) {
7344  return hasher.GetHashField();
7345  }
7346 
7347  // Do the iterative array index computation as long as there is a
7348  // chance this is an array index.
7349  while (buffer->has_more() && hasher.is_array_index()) {
7350  hasher.AddCharacter(buffer->GetNext());
7351  }
7352 
7353  // Process the remaining characters without updating the array
7354  // index.
7355  while (buffer->has_more()) {
7356  hasher.AddCharacterNoIndex(buffer->GetNext());
7357  }
7358 
7359  return hasher.GetHashField();
7360 }
7361 
7362 
7363 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) {
7364  Heap* heap = GetHeap();
7365  if (start == 0 && end == length()) return this;
7366  MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure);
7367  return result;
7368 }
7369 
7370 
7371 void String::PrintOn(FILE* file) {
7372  int length = this->length();
7373  for (int i = 0; i < length; i++) {
7374  fprintf(file, "%c", Get(i));
7375  }
7376 }
7377 
7378 
7379 static void TrimEnumCache(Heap* heap, Map* map, DescriptorArray* descriptors) {
7380  int live_enum = map->EnumLength();
7381  if (live_enum == Map::kInvalidEnumCache) {
7383  }
7384  if (live_enum == 0) return descriptors->ClearEnumCache();
7385 
7386  FixedArray* enum_cache = descriptors->GetEnumCache();
7387 
7388  int to_trim = enum_cache->length() - live_enum;
7389  if (to_trim <= 0) return;
7390  RightTrimFixedArray<FROM_GC>(heap, descriptors->GetEnumCache(), to_trim);
7391 
7392  if (!descriptors->HasEnumIndicesCache()) return;
7393  FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache();
7394  RightTrimFixedArray<FROM_GC>(heap, enum_indices_cache, to_trim);
7395 }
7396 
7397 
7398 static void TrimDescriptorArray(Heap* heap,
7399  Map* map,
7400  DescriptorArray* descriptors,
7401  int number_of_own_descriptors) {
7402  int number_of_descriptors = descriptors->number_of_descriptors();
7403  int to_trim = number_of_descriptors - number_of_own_descriptors;
7404  if (to_trim <= 0) return;
7405 
7406  RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim);
7407  descriptors->SetNumberOfDescriptors(number_of_own_descriptors);
7408 
7409  if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors);
7410  descriptors->Sort();
7411 }
7412 
7413 
7414 // Clear a possible back pointer in case the transition leads to a dead map.
7415 // Return true in case a back pointer has been cleared and false otherwise.
7416 static bool ClearBackPointer(Heap* heap, Map* target) {
7417  if (Marking::MarkBitFrom(target).Get()) return false;
7418  target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
7419  return true;
7420 }
7421 
7422 
7423 // TODO(mstarzinger): This method should be moved into MarkCompactCollector,
7424 // because it cannot be called from outside the GC and we already have methods
7425 // depending on the transitions layout in the GC anyways.
7427  // If there are no transitions to be cleared, return.
7428  // TODO(verwaest) Should be an assert, otherwise back pointers are not
7429  // properly cleared.
7430  if (!HasTransitionArray()) return;
7431 
7432  TransitionArray* t = transitions();
7433  MarkCompactCollector* collector = heap->mark_compact_collector();
7434 
7435  int transition_index = 0;
7436 
7437  DescriptorArray* descriptors = instance_descriptors();
7438  bool descriptors_owner_died = false;
7439 
7440  // Compact all live descriptors to the left.
7441  for (int i = 0; i < t->number_of_transitions(); ++i) {
7442  Map* target = t->GetTarget(i);
7443  if (ClearBackPointer(heap, target)) {
7444  if (target->instance_descriptors() == descriptors) {
7445  descriptors_owner_died = true;
7446  descriptors_owner_died = true;
7447  }
7448  } else {
7449  if (i != transition_index) {
7450  String* key = t->GetKey(i);
7451  t->SetKey(transition_index, key);
7452  Object** key_slot = t->GetKeySlot(transition_index);
7453  collector->RecordSlot(key_slot, key_slot, key);
7454  // Target slots do not need to be recorded since maps are not compacted.
7455  t->SetTarget(transition_index, t->GetTarget(i));
7456  }
7457  transition_index++;
7458  }
7459  }
7460 
7461  if (t->HasElementsTransition() &&
7462  ClearBackPointer(heap, t->elements_transition())) {
7463  if (t->elements_transition()->instance_descriptors() == descriptors) {
7464  descriptors_owner_died = true;
7465  }
7467  } else {
7468  // If there are no transitions to be cleared, return.
7469  // TODO(verwaest) Should be an assert, otherwise back pointers are not
7470  // properly cleared.
7471  if (transition_index == t->number_of_transitions()) return;
7472  }
7473 
7474  int number_of_own_descriptors = NumberOfOwnDescriptors();
7475 
7476  if (descriptors_owner_died) {
7477  if (number_of_own_descriptors > 0) {
7478  TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors);
7479  ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
7480  } else {
7481  ASSERT(descriptors == GetHeap()->empty_descriptor_array());
7482  }
7483  }
7484 
7485  int trim = t->number_of_transitions() - transition_index;
7486  if (trim > 0) {
7487  RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition()
7488  ? trim : trim * TransitionArray::kTransitionSize);
7489  }
7490 }
7491 
7492 
7493 int Map::Hash() {
7494  // For performance reasons we only hash the 3 most variable fields of a map:
7495  // constructor, prototype and bit_field2.
7496 
7497  // Shift away the tag.
7498  int hash = (static_cast<uint32_t>(
7499  reinterpret_cast<uintptr_t>(constructor())) >> 2);
7500 
7501  // XOR-ing the prototype and constructor directly yields too many zero bits
7502  // when the two pointers are close (which is fairly common).
7503  // To avoid this we shift the prototype 4 bits relatively to the constructor.
7504  hash ^= (static_cast<uint32_t>(
7505  reinterpret_cast<uintptr_t>(prototype())) << 2);
7506 
7507  return hash ^ (hash >> 16) ^ bit_field2();
7508 }
7509 
7510 
7513  return
7514  constructor() == other->constructor() &&
7515  prototype() == other->prototype() &&
7517  0 :
7518  other->inobject_properties()) &&
7519  instance_type() == other->instance_type() &&
7520  bit_field() == other->bit_field() &&
7521  bit_field2() == other->bit_field2() &&
7523 }
7524 
7525 
7526 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
7527  // Iterate over all fields in the body but take care in dealing with
7528  // the code entry.
7530  v->VisitCodeEntry(this->address() + kCodeEntryOffset);
7531  IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
7532 }
7533 
7534 
7536  ASSERT(is_compiled() && !IsOptimized());
7537  ASSERT(shared()->allows_lazy_compilation() ||
7538  code()->optimizable());
7539  Builtins* builtins = GetIsolate()->builtins();
7540  ReplaceCode(builtins->builtin(Builtins::kLazyRecompile));
7541 }
7542 
7544  ASSERT(is_compiled() && !IsOptimized());
7545  ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
7546  Builtins* builtins = GetIsolate()->builtins();
7547  ReplaceCode(builtins->builtin(Builtins::kParallelRecompile));
7548 
7549  // Unlike MarkForLazyRecompilation, after queuing a function for
7550  // recompilation on the compiler thread, we actually tail-call into
7551  // the full code. We reset the profiler ticks here so that the
7552  // function doesn't bother the runtime profiler too much.
7553  shared()->code()->set_profiler_ticks(0);
7554 }
7555 
7556 static bool CompileLazyHelper(CompilationInfo* info,
7558  // Compile the source information to a code object.
7559  ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
7560  ASSERT(!info->isolate()->has_pending_exception());
7561  bool result = Compiler::CompileLazy(info);
7562  ASSERT(result != Isolate::Current()->has_pending_exception());
7563  if (!result && flag == CLEAR_EXCEPTION) {
7564  info->isolate()->clear_pending_exception();
7565  }
7566  return result;
7567 }
7568 
7569 
7571  ClearExceptionFlag flag) {
7572  ASSERT(shared->allows_lazy_compilation_without_context());
7573  CompilationInfoWithZone info(shared);
7574  return CompileLazyHelper(&info, flag);
7575 }
7576 
7577 
7579  set_optimized_code_map(Smi::FromInt(0));
7580 }
7581 
7582 
7585  Handle<Context> native_context,
7586  Handle<Code> code,
7587  Handle<FixedArray> literals) {
7588  ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
7589  ASSERT(native_context->IsNativeContext());
7590  STATIC_ASSERT(kEntryLength == 3);
7591  Object* value = shared->optimized_code_map();
7592  Handle<FixedArray> new_code_map;
7593  if (value->IsSmi()) {
7594  // No optimized code map.
7595  ASSERT_EQ(0, Smi::cast(value)->value());
7596  // Crate 3 entries per context {context, code, literals}.
7597  new_code_map = FACTORY->NewFixedArray(kEntryLength);
7598  new_code_map->set(0, *native_context);
7599  new_code_map->set(1, *code);
7600  new_code_map->set(2, *literals);
7601  } else {
7602  // Copy old map and append one new entry.
7603  Handle<FixedArray> old_code_map(FixedArray::cast(value));
7604  ASSERT_EQ(-1, shared->SearchOptimizedCodeMap(*native_context));
7605  int old_length = old_code_map->length();
7606  int new_length = old_length + kEntryLength;
7607  new_code_map = FACTORY->NewFixedArray(new_length);
7608  old_code_map->CopyTo(0, *new_code_map, 0, old_length);
7609  new_code_map->set(old_length, *native_context);
7610  new_code_map->set(old_length + 1, *code);
7611  new_code_map->set(old_length + 2, *literals);
7612  }
7613 #ifdef DEBUG
7614  for (int i = 0; i < new_code_map->length(); i += kEntryLength) {
7615  ASSERT(new_code_map->get(i)->IsNativeContext());
7616  ASSERT(new_code_map->get(i + 1)->IsCode());
7617  ASSERT(Code::cast(new_code_map->get(i + 1))->kind() ==
7618  Code::OPTIMIZED_FUNCTION);
7619  ASSERT(new_code_map->get(i + 2)->IsFixedArray());
7620  }
7621 #endif
7622  shared->set_optimized_code_map(*new_code_map);
7623 }
7624 
7625 
7627  int index) {
7628  ASSERT(index > 0);
7629  ASSERT(optimized_code_map()->IsFixedArray());
7630  FixedArray* code_map = FixedArray::cast(optimized_code_map());
7631  if (!bound()) {
7632  FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1));
7633  ASSERT(cached_literals != NULL);
7634  function->set_literals(cached_literals);
7635  }
7636  Code* code = Code::cast(code_map->get(index));
7637  ASSERT(code != NULL);
7638  ASSERT(function->context()->native_context() == code_map->get(index - 1));
7639  function->ReplaceCode(code);
7640 }
7641 
7642 
7644  ClearExceptionFlag flag) {
7645  bool result = true;
7646  if (function->shared()->is_compiled()) {
7647  function->ReplaceCode(function->shared()->code());
7648  function->shared()->set_code_age(0);
7649  } else {
7650  ASSERT(function->shared()->allows_lazy_compilation());
7651  CompilationInfoWithZone info(function);
7652  result = CompileLazyHelper(&info, flag);
7653  ASSERT(!result || function->is_compiled());
7654  }
7655  return result;
7656 }
7657 
7658 
7660  BailoutId osr_ast_id,
7661  ClearExceptionFlag flag) {
7662  CompilationInfoWithZone info(function);
7663  info.SetOptimizing(osr_ast_id);
7664  return CompileLazyHelper(&info, flag);
7665 }
7666 
7667 
7669  ClearExceptionFlag flag) {
7670  return function->is_compiled() || CompileLazy(function, flag);
7671 }
7672 
7673 
7675  if (IsBuiltin()) return false;
7676  SharedFunctionInfo* shared_info = shared();
7677  // Check that the function has a script associated with it.
7678  if (!shared_info->script()->IsScript()) return false;
7679  if (shared_info->optimization_disabled()) return false;
7680  Code* code = shared_info->code();
7681  if (code->kind() == Code::OPTIMIZED_FUNCTION) return true;
7682  // If we never ran this (unlikely) then lets try to optimize it.
7683  if (code->kind() != Code::FUNCTION) return true;
7684  return code->optimizable();
7685 }
7686 
7687 
7689  if (IsGlobalObject()) return this;
7690 
7691  // Make sure prototypes are fast objects and their maps have the bit set
7692  // so they remain fast.
7693  if (!HasFastProperties()) {
7694  MaybeObject* new_proto = TransformToFastProperties(0);
7695  if (new_proto->IsFailure()) return new_proto;
7696  ASSERT(new_proto == this);
7697  }
7698  return this;
7699 }
7700 
7701 
7703  ASSERT(value->IsJSReceiver());
7704  Heap* heap = GetHeap();
7705 
7706  // First some logic for the map of the prototype to make sure it is in fast
7707  // mode.
7708  if (value->IsJSObject()) {
7709  MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
7710  if (ok->IsFailure()) return ok;
7711  }
7712 
7713  // Now some logic for the maps of the objects that are created by using this
7714  // function as a constructor.
7715  if (has_initial_map()) {
7716  // If the function has allocated the initial map
7717  // replace it with a copy containing the new prototype.
7718  Map* new_map;
7719  MaybeObject* maybe_new_map = initial_map()->Copy();
7720  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7721  new_map->set_prototype(value);
7722  MaybeObject* maybe_object = set_initial_map_and_cache_transitions(new_map);
7723  if (maybe_object->IsFailure()) return maybe_object;
7724  } else {
7725  // Put the value in the initial map field until an initial map is
7726  // needed. At that point, a new initial map is created and the
7727  // prototype is put into the initial map where it belongs.
7728  set_prototype_or_initial_map(value);
7729  }
7730  heap->ClearInstanceofCache();
7731  return value;
7732 }
7733 
7734 
7735 MaybeObject* JSFunction::SetPrototype(Object* value) {
7737  Object* construct_prototype = value;
7738 
7739  // If the value is not a JSReceiver, store the value in the map's
7740  // constructor field so it can be accessed. Also, set the prototype
7741  // used for constructing objects to the original object prototype.
7742  // See ECMA-262 13.2.2.
7743  if (!value->IsJSReceiver()) {
7744  // Copy the map so this does not affect unrelated functions.
7745  // Remove map transitions because they point to maps with a
7746  // different prototype.
7747  Map* new_map;
7748  MaybeObject* maybe_new_map = map()->Copy();
7749  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7750 
7751  Heap* heap = new_map->GetHeap();
7752  set_map(new_map);
7753  new_map->set_constructor(value);
7754  new_map->set_non_instance_prototype(true);
7755  construct_prototype =
7756  heap->isolate()->context()->native_context()->
7757  initial_object_prototype();
7758  } else {
7759  map()->set_non_instance_prototype(false);
7760  }
7761 
7762  return SetInstancePrototype(construct_prototype);
7763 }
7764 
7765 
7767  Context* native_context = context()->native_context();
7768  Map* no_prototype_map = shared()->is_classic_mode()
7769  ? native_context->function_without_prototype_map()
7770  : native_context->strict_mode_function_without_prototype_map();
7771 
7772  if (map() == no_prototype_map) return;
7773 
7774  ASSERT(map() == (shared()->is_classic_mode()
7775  ? native_context->function_map()
7776  : native_context->strict_mode_function_map()));
7777 
7778  set_map(no_prototype_map);
7779  set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
7780 }
7781 
7782 
7784  shared()->set_instance_class_name(name);
7785 }
7786 
7787 
7788 void JSFunction::PrintName(FILE* out) {
7789  SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
7790  PrintF(out, "%s", *name);
7791 }
7792 
7793 
7796 }
7797 
7798 
7799 MaybeObject* Oddball::Initialize(const char* to_string,
7800  Object* to_number,
7801  byte kind) {
7802  String* symbol;
7803  { MaybeObject* maybe_symbol =
7804  Isolate::Current()->heap()->LookupAsciiSymbol(to_string);
7805  if (!maybe_symbol->To(&symbol)) return maybe_symbol;
7806  }
7807  set_to_string(symbol);
7808  set_to_number(to_number);
7809  set_kind(kind);
7810  return this;
7811 }
7812 
7813 
7815  Object* n = name();
7816  if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
7817  return String::cast(n);
7818 }
7819 
7820 
7822  return !script()->IsUndefined() &&
7823  !reinterpret_cast<Script*>(script())->source()->IsUndefined();
7824 }
7825 
7826 
7828  if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
7829  Handle<String> source(String::cast(Script::cast(script())->source()));
7830  return SubString(source, start_position(), end_position());
7831 }
7832 
7833 
7835  return end_position() - start_position();
7836 }
7837 
7838 
7840  int instance_size =
7843  if (instance_size > JSObject::kMaxInstanceSize) {
7844  instance_size = JSObject::kMaxInstanceSize;
7845  }
7846  return instance_size;
7847 }
7848 
7849 
7852 }
7853 
7854 
7856  // Check the basic conditions for generating inline constructor code.
7857  if (!FLAG_inline_new
7859  || this_property_assignments_count() == 0) {
7860  return false;
7861  }
7862 
7863  Heap* heap = GetHeap();
7864 
7865  // Traverse the proposed prototype chain looking for properties of the
7866  // same names as are set by the inline constructor.
7867  for (Object* obj = prototype;
7868  obj != heap->null_value();
7869  obj = obj->GetPrototype()) {
7870  JSReceiver* receiver = JSReceiver::cast(obj);
7871  for (int i = 0; i < this_property_assignments_count(); i++) {
7872  LookupResult result(heap->isolate());
7874  receiver->LocalLookup(name, &result);
7875  if (result.IsFound()) {
7876  switch (result.type()) {
7877  case NORMAL:
7878  case FIELD:
7879  case CONSTANT_FUNCTION:
7880  break;
7881  case INTERCEPTOR:
7882  case CALLBACKS:
7883  case HANDLER:
7884  return false;
7885  case TRANSITION:
7886  case NONEXISTENT:
7887  UNREACHABLE();
7888  break;
7889  }
7890  }
7891  }
7892  }
7893 
7894  return true;
7895 }
7896 
7897 
7901  false));
7902 }
7903 
7904 
7906  bool only_simple_this_property_assignments,
7907  FixedArray* assignments) {
7910  only_simple_this_property_assignments));
7911  set_this_property_assignments(assignments);
7912  set_this_property_assignments_count(assignments->length() / 3);
7913 }
7914 
7915 
7917  Heap* heap = GetHeap();
7920  false));
7921  set_this_property_assignments(heap->undefined_value());
7923 }
7924 
7925 
7927  Object* obj = this_property_assignments();
7928  ASSERT(obj->IsFixedArray());
7930  obj = FixedArray::cast(obj)->get(index * 3);
7931  ASSERT(obj->IsString());
7932  return String::cast(obj);
7933 }
7934 
7935 
7937  Object* obj = this_property_assignments();
7938  ASSERT(obj->IsFixedArray());
7940  obj = FixedArray::cast(obj)->get(index * 3 + 1);
7941  return Smi::cast(obj)->value() != -1;
7942 }
7943 
7944 
7947  Object* obj =
7948  FixedArray::cast(this_property_assignments())->get(index * 3 + 1);
7949  return Smi::cast(obj)->value();
7950 }
7951 
7952 
7955  Object* obj =
7956  FixedArray::cast(this_property_assignments())->get(index * 3 + 2);
7957  return obj;
7958 }
7959 
7960 
7961 // Support function for printing the source code to a StringStream
7962 // without any allocation in the heap.
7964  int max_length) {
7965  // For some native functions there is no source.
7966  if (!HasSourceCode()) {
7967  accumulator->Add("<No Source>");
7968  return;
7969  }
7970 
7971  // Get the source for the script which this function came from.
7972  // Don't use String::cast because we don't want more assertion errors while
7973  // we are already creating a stack dump.
7974  String* script_source =
7975  reinterpret_cast<String*>(Script::cast(script())->source());
7976 
7977  if (!script_source->LooksValid()) {
7978  accumulator->Add("<Invalid Source>");
7979  return;
7980  }
7981 
7982  if (!is_toplevel()) {
7983  accumulator->Add("function ");
7984  Object* name = this->name();
7985  if (name->IsString() && String::cast(name)->length() > 0) {
7986  accumulator->PrintName(name);
7987  }
7988  }
7989 
7990  int len = end_position() - start_position();
7991  if (len <= max_length || max_length < 0) {
7992  accumulator->Put(script_source, start_position(), end_position());
7993  } else {
7994  accumulator->Put(script_source,
7995  start_position(),
7996  start_position() + max_length);
7997  accumulator->Add("...\n");
7998  }
7999 }
8000 
8001 
8002 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
8003  if (code->instruction_size() != recompiled->instruction_size()) return false;
8004  ByteArray* code_relocation = code->relocation_info();
8005  ByteArray* recompiled_relocation = recompiled->relocation_info();
8006  int length = code_relocation->length();
8007  if (length != recompiled_relocation->length()) return false;
8008  int compare = memcmp(code_relocation->GetDataStartAddress(),
8009  recompiled_relocation->GetDataStartAddress(),
8010  length);
8011  return compare == 0;
8012 }
8013 
8014 
8017  AssertNoAllocation no_allocation;
8018  Code* code = this->code();
8019  if (IsCodeEquivalent(code, recompiled)) {
8020  // Copy the deoptimization data from the recompiled code.
8021  code->set_deoptimization_data(recompiled->deoptimization_data());
8022  code->set_has_deoptimization_support(true);
8023  } else {
8024  // TODO(3025757): In case the recompiled isn't equivalent to the
8025  // old code, we have to replace it. We should try to avoid this
8026  // altogether because it flushes valuable type feedback by
8027  // effectively resetting all IC state.
8028  set_code(recompiled);
8029  }
8031 }
8032 
8033 
8035  // Disable optimization for the shared function info and mark the
8036  // code as non-optimizable. The marker on the shared function info
8037  // is there because we flush non-optimized code thereby loosing the
8038  // non-optimizable information for the code. When the code is
8039  // regenerated and set on the shared function info it is marked as
8040  // non-optimizable if optimization is disabled for the shared
8041  // function info.
8042  set_optimization_disabled(true);
8043  // Code should be the lazy compilation stub or else unoptimized. If the
8044  // latter, disable optimization for the code too.
8045  ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
8046  if (code()->kind() == Code::FUNCTION) {
8047  code()->set_optimizable(false);
8048  }
8049  if (FLAG_trace_opt) {
8050  PrintF("[disabled optimization for %s, reason: %s]\n",
8051  *DebugName()->ToCString(), reason);
8052  }
8053 }
8054 
8055 
8057  ASSERT(!id.IsNone());
8058  Code* unoptimized = code();
8059  DeoptimizationOutputData* data =
8060  DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
8061  unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
8062  USE(ignore);
8063  return true; // Return true if there was no ASSERT.
8064 }
8065 
8066 
8069 
8070  if (!FLAG_clever_optimizations) return;
8071 
8072  // Only initiate the tracking the first time.
8073  if (live_objects_may_exist()) return;
8074  set_live_objects_may_exist(true);
8075 
8076  // No tracking during the snapshot construction phase.
8077  if (Serializer::enabled()) return;
8078 
8079  if (map->unused_property_fields() == 0) return;
8080 
8081  // Nonzero counter is a leftover from the previous attempt interrupted
8082  // by GC, keep it.
8083  if (construction_count() == 0) {
8085  }
8086  set_initial_map(map);
8087  Builtins* builtins = map->GetHeap()->isolate()->builtins();
8088  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
8089  construct_stub());
8090  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
8091 }
8092 
8093 
8094 // Called from GC, hence reinterpret_cast and unchecked accessors.
8096  Map* map = reinterpret_cast<Map*>(initial_map());
8097 
8098  // Make the map remember to restore the link if it survives the GC.
8099  map->set_bit_field2(
8101 
8102  // Undo state changes made by StartInobjectTracking (except the
8103  // construction_count). This way if the initial map does not survive the GC
8104  // then StartInobjectTracking will be called again the next time the
8105  // constructor is called. The countdown will continue and (possibly after
8106  // several more GCs) CompleteInobjectSlackTracking will eventually be called.
8107  Heap* heap = map->GetHeap();
8108  set_initial_map(heap->raw_unchecked_undefined_value());
8109  Builtins* builtins = heap->isolate()->builtins();
8110  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
8111  *RawField(this, kConstructStubOffset));
8112  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
8113  // It is safe to clear the flag: it will be set again if the map is live.
8114  set_live_objects_may_exist(false);
8115 }
8116 
8117 
8118 // Called from GC, hence reinterpret_cast and unchecked accessors.
8120  map->set_bit_field2(
8122 
8123  // Resume inobject slack tracking.
8124  set_initial_map(map);
8125  Builtins* builtins = map->GetHeap()->isolate()->builtins();
8126  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
8127  *RawField(this, kConstructStubOffset));
8128  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
8129  // The map survived the gc, so there may be objects referencing it.
8130  set_live_objects_may_exist(true);
8131 }
8132 
8133 
8135  code()->ClearInlineCaches();
8136  set_ic_age(new_ic_age);
8137  if (code()->kind() == Code::FUNCTION) {
8138  code()->set_profiler_ticks(0);
8139  if (optimization_disabled() &&
8140  opt_count() >= FLAG_max_opt_count) {
8141  // Re-enable optimizations if they were disabled due to opt_count limit.
8142  set_optimization_disabled(false);
8143  code()->set_optimizable(true);
8144  }
8145  set_opt_count(0);
8146  set_deopt_count(0);
8147  }
8148 }
8149 
8150 
8151 static void GetMinInobjectSlack(Map* map, void* data) {
8152  int slack = map->unused_property_fields();
8153  if (*reinterpret_cast<int*>(data) > slack) {
8154  *reinterpret_cast<int*>(data) = slack;
8155  }
8156 }
8157 
8158 
8159 static void ShrinkInstanceSize(Map* map, void* data) {
8160  int slack = *reinterpret_cast<int*>(data);
8161  map->set_inobject_properties(map->inobject_properties() - slack);
8162  map->set_unused_property_fields(map->unused_property_fields() - slack);
8163  map->set_instance_size(map->instance_size() - slack * kPointerSize);
8164 
8165  // Visitor id might depend on the instance size, recalculate it.
8166  map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
8167 }
8168 
8169 
8171  ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress());
8172  Map* map = Map::cast(initial_map());
8173 
8174  Heap* heap = map->GetHeap();
8175  set_initial_map(heap->undefined_value());
8176  Builtins* builtins = heap->isolate()->builtins();
8177  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
8178  construct_stub());
8179  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
8180 
8181  int slack = map->unused_property_fields();
8182  map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
8183  if (slack != 0) {
8184  // Resize the initial map and all maps in its transition tree.
8185  map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
8186 
8187  // Give the correct expected_nof_properties to initial maps created later.
8188  ASSERT(expected_nof_properties() >= slack);
8190  }
8191 }
8192 
8193 
8195  ASSERT(native_context->IsNativeContext());
8196  if (!FLAG_cache_optimized_code) return -1;
8197  Object* value = optimized_code_map();
8198  if (!value->IsSmi()) {
8199  FixedArray* optimized_code_map = FixedArray::cast(value);
8200  int length = optimized_code_map->length();
8201  for (int i = 0; i < length; i += 3) {
8202  if (optimized_code_map->get(i) == native_context) {
8203  return i + 1;
8204  }
8205  }
8206  }
8207  return -1;
8208 }
8209 
8210 
8211 #define DECLARE_TAG(ignore1, name, ignore2) name,
8212 const char* const VisitorSynchronization::kTags[
8215 };
8216 #undef DECLARE_TAG
8217 
8218 
8219 #define DECLARE_TAG(ignore1, ignore2, name) name,
8220 const char* const VisitorSynchronization::kTagNames[
8223 };
8224 #undef DECLARE_TAG
8225 
8226 
8227 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
8228  ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
8229  Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
8230  Object* old_target = target;
8231  VisitPointer(&target);
8232  CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target.
8233 }
8234 
8235 
8236 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
8237  Object* code = Code::GetObjectFromEntryAddress(entry_address);
8238  Object* old_code = code;
8239  VisitPointer(&code);
8240  if (code != old_code) {
8241  Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
8242  }
8243 }
8244 
8245 
8246 void ObjectVisitor::VisitGlobalPropertyCell(RelocInfo* rinfo) {
8247  ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
8248  Object* cell = rinfo->target_cell();
8249  Object* old_cell = cell;
8250  VisitPointer(&cell);
8251  if (cell != old_cell) {
8252  rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell));
8253  }
8254 }
8255 
8256 
8257 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
8258  ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
8259  rinfo->IsPatchedReturnSequence()) ||
8260  (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
8261  rinfo->IsPatchedDebugBreakSlotSequence()));
8262  Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
8263  Object* old_target = target;
8264  VisitPointer(&target);
8265  CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target.
8266 }
8267 
8268 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
8269  ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
8270  VisitPointer(rinfo->target_object_address());
8271 }
8272 
8273 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
8274  Address* p = rinfo->target_reference_address();
8275  VisitExternalReferences(p, p + 1);
8276 }
8277 
8279  set_relocation_info(GetHeap()->empty_byte_array());
8280 }
8281 
8282 
8283 void Code::Relocate(intptr_t delta) {
8284  for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
8285  it.rinfo()->apply(delta);
8286  }
8288 }
8289 
8290 
8291 void Code::CopyFrom(const CodeDesc& desc) {
8292  ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT);
8293 
8294  // copy code
8295  memmove(instruction_start(), desc.buffer, desc.instr_size);
8296 
8297  // copy reloc info
8298  memmove(relocation_start(),
8299  desc.buffer + desc.buffer_size - desc.reloc_size,
8300  desc.reloc_size);
8301 
8302  // unbox handles and relocate
8303  intptr_t delta = instruction_start() - desc.buffer;
8304  int mode_mask = RelocInfo::kCodeTargetMask |
8305  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
8306  RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
8307  RelocInfo::kApplyMask;
8308  Assembler* origin = desc.origin; // Needed to find target_object on X64.
8309  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
8310  RelocInfo::Mode mode = it.rinfo()->rmode();
8311  if (mode == RelocInfo::EMBEDDED_OBJECT) {
8312  Handle<Object> p = it.rinfo()->target_object_handle(origin);
8313  it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER);
8314  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
8315  Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle();
8316  it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER);
8317  } else if (RelocInfo::IsCodeTarget(mode)) {
8318  // rewrite code handles in inline cache targets to direct
8319  // pointers to the first instruction in the code object
8320  Handle<Object> p = it.rinfo()->target_object_handle(origin);
8321  Code* code = Code::cast(*p);
8322  it.rinfo()->set_target_address(code->instruction_start(),
8324  } else {
8325  it.rinfo()->apply(delta);
8326  }
8327  }
8329 }
8330 
8331 
8332 // Locate the source position which is closest to the address in the code. This
8333 // is using the source position information embedded in the relocation info.
8334 // The position returned is relative to the beginning of the script where the
8335 // source for this function is found.
8337  int distance = kMaxInt;
8338  int position = RelocInfo::kNoPosition; // Initially no position found.
8339  // Run through all the relocation info to find the best matching source
8340  // position. All the code needs to be considered as the sequence of the
8341  // instructions in the code does not necessarily follow the same order as the
8342  // source.
8343  RelocIterator it(this, RelocInfo::kPositionMask);
8344  while (!it.done()) {
8345  // Only look at positions after the current pc.
8346  if (it.rinfo()->pc() < pc) {
8347  // Get position and distance.
8348 
8349  int dist = static_cast<int>(pc - it.rinfo()->pc());
8350  int pos = static_cast<int>(it.rinfo()->data());
8351  // If this position is closer than the current candidate or if it has the
8352  // same distance as the current candidate and the position is higher then
8353  // this position is the new candidate.
8354  if ((dist < distance) ||
8355  (dist == distance && pos > position)) {
8356  position = pos;
8357  distance = dist;
8358  }
8359  }
8360  it.next();
8361  }
8362  return position;
8363 }
8364 
8365 
8366 // Same as Code::SourcePosition above except it only looks for statement
8367 // positions.
8369  // First find the position as close as possible using all position
8370  // information.
8371  int position = SourcePosition(pc);
8372  // Now find the closest statement position before the position.
8373  int statement_position = 0;
8374  RelocIterator it(this, RelocInfo::kPositionMask);
8375  while (!it.done()) {
8376  if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
8377  int p = static_cast<int>(it.rinfo()->data());
8378  if (statement_position < p && p <= position) {
8379  statement_position = p;
8380  }
8381  }
8382  it.next();
8383  }
8384  return statement_position;
8385 }
8386 
8387 
8389  SafepointTable table(this);
8390  return table.FindEntry(pc);
8391 }
8392 
8393 
8395  // Indicate the absence of a stack-check table by a table start after the
8396  // end of the instructions. Table start must be aligned, so round up.
8398 }
8399 
8400 
8403  AssertNoAllocation no_allocation;
8404  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
8405  for (RelocIterator it(this, mask); !it.done(); it.next()) {
8406  RelocInfo* info = it.rinfo();
8407  Object* object = info->target_object();
8408  if (object->IsMap()) return Map::cast(object);
8409  }
8410  return NULL;
8411 }
8412 
8413 
8415  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
8416  RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
8417  RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
8418  RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
8419  for (RelocIterator it(this, mask); !it.done(); it.next()) {
8420  RelocInfo* info = it.rinfo();
8421  Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
8422  if (target->is_inline_cache_stub()) {
8423  IC::Clear(info->pc());
8424  }
8425  }
8426 }
8427 
8428 
8430  Object* raw_info = type_feedback_info();
8431  if (raw_info->IsTypeFeedbackInfo()) {
8432  TypeFeedbackCells* type_feedback_cells =
8433  TypeFeedbackInfo::cast(raw_info)->type_feedback_cells();
8434  for (int i = 0; i < type_feedback_cells->CellCount(); i++) {
8435  JSGlobalPropertyCell* cell = type_feedback_cells->Cell(i);
8436  cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap));
8437  }
8438  }
8439 }
8440 
8441 
8443  return is_keyed_load_stub() || is_keyed_store_stub() ||
8445 }
8446 
8447 
8448 #ifdef ENABLE_DISASSEMBLER
8449 
8450 void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
8451  disasm::NameConverter converter;
8452  int deopt_count = DeoptCount();
8453  PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
8454  if (0 == deopt_count) return;
8455 
8456  PrintF(out, "%6s %6s %6s %6s %12s\n", "index", "ast id", "argc", "pc",
8457  FLAG_print_code_verbose ? "commands" : "");
8458  for (int i = 0; i < deopt_count; i++) {
8459  PrintF(out, "%6d %6d %6d %6d",
8460  i,
8461  AstId(i).ToInt(),
8462  ArgumentsStackHeight(i)->value(),
8463  Pc(i)->value());
8464 
8465  if (!FLAG_print_code_verbose) {
8466  PrintF(out, "\n");
8467  continue;
8468  }
8469  // Print details of the frame translation.
8470  int translation_index = TranslationIndex(i)->value();
8471  TranslationIterator iterator(TranslationByteArray(), translation_index);
8472  Translation::Opcode opcode =
8473  static_cast<Translation::Opcode>(iterator.Next());
8474  ASSERT(Translation::BEGIN == opcode);
8475  int frame_count = iterator.Next();
8476  int jsframe_count = iterator.Next();
8477  PrintF(out, " %s {frame count=%d, js frame count=%d}\n",
8478  Translation::StringFor(opcode),
8479  frame_count,
8480  jsframe_count);
8481 
8482  while (iterator.HasNext() &&
8483  Translation::BEGIN !=
8484  (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
8485  PrintF(out, "%24s %s ", "", Translation::StringFor(opcode));
8486 
8487  switch (opcode) {
8488  case Translation::BEGIN:
8489  UNREACHABLE();
8490  break;
8491 
8492  case Translation::JS_FRAME: {
8493  int ast_id = iterator.Next();
8494  int function_id = iterator.Next();
8495  unsigned height = iterator.Next();
8496  PrintF(out, "{ast_id=%d, function=", ast_id);
8497  if (function_id != Translation::kSelfLiteralId) {
8498  Object* function = LiteralArray()->get(function_id);
8499  JSFunction::cast(function)->PrintName(out);
8500  } else {
8501  PrintF(out, "<self>");
8502  }
8503  PrintF(out, ", height=%u}", height);
8504  break;
8505  }
8506 
8507  case Translation::ARGUMENTS_ADAPTOR_FRAME:
8508  case Translation::CONSTRUCT_STUB_FRAME: {
8509  int function_id = iterator.Next();
8510  JSFunction* function =
8511  JSFunction::cast(LiteralArray()->get(function_id));
8512  unsigned height = iterator.Next();
8513  PrintF(out, "{function=");
8514  function->PrintName(out);
8515  PrintF(out, ", height=%u}", height);
8516  break;
8517  }
8518 
8519  case Translation::GETTER_STUB_FRAME:
8520  case Translation::SETTER_STUB_FRAME: {
8521  int function_id = iterator.Next();
8522  JSFunction* function =
8523  JSFunction::cast(LiteralArray()->get(function_id));
8524  PrintF(out, "{function=");
8525  function->PrintName(out);
8526  PrintF(out, "}");
8527  break;
8528  }
8529 
8530  case Translation::DUPLICATE:
8531  break;
8532 
8533  case Translation::REGISTER: {
8534  int reg_code = iterator.Next();
8535  PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
8536  break;
8537  }
8538 
8539  case Translation::INT32_REGISTER: {
8540  int reg_code = iterator.Next();
8541  PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
8542  break;
8543  }
8544 
8545  case Translation::UINT32_REGISTER: {
8546  int reg_code = iterator.Next();
8547  PrintF(out,
8548  "{input=%s (unsigned)}",
8549  converter.NameOfCPURegister(reg_code));
8550  break;
8551  }
8552 
8553  case Translation::DOUBLE_REGISTER: {
8554  int reg_code = iterator.Next();
8555  PrintF(out, "{input=%s}",
8557  break;
8558  }
8559 
8560  case Translation::STACK_SLOT: {
8561  int input_slot_index = iterator.Next();
8562  PrintF(out, "{input=%d}", input_slot_index);
8563  break;
8564  }
8565 
8566  case Translation::INT32_STACK_SLOT: {
8567  int input_slot_index = iterator.Next();
8568  PrintF(out, "{input=%d}", input_slot_index);
8569  break;
8570  }
8571 
8572  case Translation::UINT32_STACK_SLOT: {
8573  int input_slot_index = iterator.Next();
8574  PrintF(out, "{input=%d (unsigned)}", input_slot_index);
8575  break;
8576  }
8577 
8578  case Translation::DOUBLE_STACK_SLOT: {
8579  int input_slot_index = iterator.Next();
8580  PrintF(out, "{input=%d}", input_slot_index);
8581  break;
8582  }
8583 
8584  case Translation::LITERAL: {
8585  unsigned literal_index = iterator.Next();
8586  PrintF(out, "{literal_id=%u}", literal_index);
8587  break;
8588  }
8589 
8590  case Translation::ARGUMENTS_OBJECT:
8591  break;
8592  }
8593  PrintF(out, "\n");
8594  }
8595  }
8596 }
8597 
8598 
8599 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
8600  PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
8601  this->DeoptPoints());
8602  if (this->DeoptPoints() == 0) return;
8603 
8604  PrintF("%6s %8s %s\n", "ast id", "pc", "state");
8605  for (int i = 0; i < this->DeoptPoints(); i++) {
8606  int pc_and_state = this->PcAndState(i)->value();
8607  PrintF("%6d %8d %s\n",
8608  this->AstId(i).ToInt(),
8609  FullCodeGenerator::PcField::decode(pc_and_state),
8611  FullCodeGenerator::StateField::decode(pc_and_state)));
8612  }
8613 }
8614 
8615 
8616 // Identify kind of code.
8617 const char* Code::Kind2String(Kind kind) {
8618  switch (kind) {
8619  case FUNCTION: return "FUNCTION";
8620  case OPTIMIZED_FUNCTION: return "OPTIMIZED_FUNCTION";
8621  case STUB: return "STUB";
8622  case BUILTIN: return "BUILTIN";
8623  case LOAD_IC: return "LOAD_IC";
8624  case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
8625  case STORE_IC: return "STORE_IC";
8626  case KEYED_STORE_IC: return "KEYED_STORE_IC";
8627  case CALL_IC: return "CALL_IC";
8628  case KEYED_CALL_IC: return "KEYED_CALL_IC";
8629  case UNARY_OP_IC: return "UNARY_OP_IC";
8630  case BINARY_OP_IC: return "BINARY_OP_IC";
8631  case COMPARE_IC: return "COMPARE_IC";
8632  case TO_BOOLEAN_IC: return "TO_BOOLEAN_IC";
8633  }
8634  UNREACHABLE();
8635  return NULL;
8636 }
8637 
8638 
8639 const char* Code::ICState2String(InlineCacheState state) {
8640  switch (state) {
8641  case UNINITIALIZED: return "UNINITIALIZED";
8642  case PREMONOMORPHIC: return "PREMONOMORPHIC";
8643  case MONOMORPHIC: return "MONOMORPHIC";
8644  case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
8645  case MEGAMORPHIC: return "MEGAMORPHIC";
8646  case DEBUG_BREAK: return "DEBUG_BREAK";
8647  case DEBUG_PREPARE_STEP_IN: return "DEBUG_PREPARE_STEP_IN";
8648  }
8649  UNREACHABLE();
8650  return NULL;
8651 }
8652 
8653 
8654 const char* Code::StubType2String(StubType type) {
8655  switch (type) {
8656  case NORMAL: return "NORMAL";
8657  case FIELD: return "FIELD";
8658  case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
8659  case CALLBACKS: return "CALLBACKS";
8660  case INTERCEPTOR: return "INTERCEPTOR";
8661  case MAP_TRANSITION: return "MAP_TRANSITION";
8662  case NONEXISTENT: return "NONEXISTENT";
8663  }
8664  UNREACHABLE(); // keep the compiler happy
8665  return NULL;
8666 }
8667 
8668 
8669 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
8670  const char* name = NULL;
8671  switch (kind) {
8672  case CALL_IC:
8673  if (extra == STRING_INDEX_OUT_OF_BOUNDS) {
8674  name = "STRING_INDEX_OUT_OF_BOUNDS";
8675  }
8676  break;
8677  case STORE_IC:
8678  case KEYED_STORE_IC:
8679  if (extra == kStrictMode) {
8680  name = "STRICT";
8681  }
8682  break;
8683  default:
8684  break;
8685  }
8686  if (name != NULL) {
8687  PrintF(out, "extra_ic_state = %s\n", name);
8688  } else {
8689  PrintF(out, "extra_ic_state = %d\n", extra);
8690  }
8691 }
8692 
8693 
8694 void Code::Disassemble(const char* name, FILE* out) {
8695  PrintF(out, "kind = %s\n", Kind2String(kind()));
8696  if (is_inline_cache_stub()) {
8697  PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
8698  PrintExtraICState(out, kind(), extra_ic_state());
8699  if (ic_state() == MONOMORPHIC) {
8700  PrintF(out, "type = %s\n", StubType2String(type()));
8701  }
8702  if (is_call_stub() || is_keyed_call_stub()) {
8703  PrintF(out, "argc = %d\n", arguments_count());
8704  }
8705  if (is_compare_ic_stub()) {
8707  PrintF(out, "compare_state = %s\n", CompareIC::GetStateName(state));
8708  }
8709  if (is_compare_ic_stub() && major_key() == CodeStub::CompareIC) {
8711  PrintF(out, "compare_operation = %s\n", Token::Name(op));
8712  }
8713  }
8714  if ((name != NULL) && (name[0] != '\0')) {
8715  PrintF(out, "name = %s\n", name);
8716  }
8717  if (kind() == OPTIMIZED_FUNCTION) {
8718  PrintF(out, "stack_slots = %d\n", stack_slots());
8719  }
8720 
8721  PrintF(out, "Instructions (size = %d)\n", instruction_size());
8722  Disassembler::Decode(out, this);
8723  PrintF(out, "\n");
8724 
8725  if (kind() == FUNCTION) {
8726  DeoptimizationOutputData* data =
8727  DeoptimizationOutputData::cast(this->deoptimization_data());
8728  data->DeoptimizationOutputDataPrint(out);
8729  } else if (kind() == OPTIMIZED_FUNCTION) {
8730  DeoptimizationInputData* data =
8731  DeoptimizationInputData::cast(this->deoptimization_data());
8732  data->DeoptimizationInputDataPrint(out);
8733  }
8734  PrintF("\n");
8735 
8736  if (kind() == OPTIMIZED_FUNCTION) {
8737  SafepointTable table(this);
8738  PrintF(out, "Safepoints (size = %u)\n", table.size());
8739  for (unsigned i = 0; i < table.length(); i++) {
8740  unsigned pc_offset = table.GetPcOffset(i);
8741  PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset);
8742  table.PrintEntry(i);
8743  PrintF(out, " (sp -> fp)");
8744  SafepointEntry entry = table.GetEntry(i);
8745  if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
8746  PrintF(out, " %6d", entry.deoptimization_index());
8747  } else {
8748  PrintF(out, " <none>");
8749  }
8750  if (entry.argument_count() > 0) {
8751  PrintF(out, " argc: %d", entry.argument_count());
8752  }
8753  PrintF(out, "\n");
8754  }
8755  PrintF(out, "\n");
8756  // Just print if type feedback info is ever used for optimized code.
8757  ASSERT(type_feedback_info()->IsUndefined());
8758  } else if (kind() == FUNCTION) {
8759  unsigned offset = stack_check_table_offset();
8760  // If there is no stack check table, the "table start" will at or after
8761  // (due to alignment) the end of the instruction stream.
8762  if (static_cast<int>(offset) < instruction_size()) {
8763  unsigned* address =
8764  reinterpret_cast<unsigned*>(instruction_start() + offset);
8765  unsigned length = address[0];
8766  PrintF(out, "Stack checks (size = %u)\n", length);
8767  PrintF(out, "ast_id pc_offset\n");
8768  for (unsigned i = 0; i < length; ++i) {
8769  unsigned index = (2 * i) + 1;
8770  PrintF(out, "%6u %9u\n", address[index], address[index + 1]);
8771  }
8772  PrintF(out, "\n");
8773  }
8774 #ifdef OBJECT_PRINT
8775  if (!type_feedback_info()->IsUndefined()) {
8776  TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(out);
8777  PrintF(out, "\n");
8778  }
8779 #endif
8780  }
8781 
8782  PrintF("RelocInfo (size = %d)\n", relocation_size());
8783  for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
8784  PrintF(out, "\n");
8785 }
8786 #endif // ENABLE_DISASSEMBLER
8787 
8788 
8790  int capacity,
8791  int length,
8792  SetFastElementsCapacitySmiMode smi_mode) {
8793  Heap* heap = GetHeap();
8794  // We should never end in here with a pixel or external array.
8796 
8797  // Allocate a new fast elements backing store.
8798  FixedArray* new_elements;
8799  { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
8800  if (!maybe->To(&new_elements)) return maybe;
8801  }
8802 
8803  ElementsKind elements_kind = GetElementsKind();
8804  ElementsKind new_elements_kind;
8805  // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
8806  // or if it's allowed and the old elements array contained only SMIs.
8807  bool has_fast_smi_elements =
8808  (smi_mode == kForceSmiElements) ||
8809  ((smi_mode == kAllowSmiElements) && HasFastSmiElements());
8810  if (has_fast_smi_elements) {
8811  if (IsHoleyElementsKind(elements_kind)) {
8812  new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
8813  } else {
8814  new_elements_kind = FAST_SMI_ELEMENTS;
8815  }
8816  } else {
8817  if (IsHoleyElementsKind(elements_kind)) {
8818  new_elements_kind = FAST_HOLEY_ELEMENTS;
8819  } else {
8820  new_elements_kind = FAST_ELEMENTS;
8821  }
8822  }
8823  FixedArrayBase* old_elements = elements();
8824  ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8825  { MaybeObject* maybe_obj =
8826  accessor->CopyElements(this, new_elements, new_elements_kind);
8827  if (maybe_obj->IsFailure()) return maybe_obj;
8828  }
8829  if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8830  Map* new_map = map();
8831  if (new_elements_kind != elements_kind) {
8832  MaybeObject* maybe =
8833  GetElementsTransitionMap(GetIsolate(), new_elements_kind);
8834  if (!maybe->To(&new_map)) return maybe;
8835  }
8836  ValidateElements();
8837  set_map_and_elements(new_map, new_elements);
8838  } else {
8839  FixedArray* parameter_map = FixedArray::cast(old_elements);
8840  parameter_map->set(1, new_elements);
8841  }
8842 
8843  if (FLAG_trace_elements_transitions) {
8844  PrintElementsTransition(stdout, elements_kind, old_elements,
8845  GetElementsKind(), new_elements);
8846  }
8847 
8848  if (IsJSArray()) {
8849  JSArray::cast(this)->set_length(Smi::FromInt(length));
8850  }
8851  return new_elements;
8852 }
8853 
8854 
8856  int capacity,
8857  int length) {
8858  Heap* heap = GetHeap();
8859  // We should never end in here with a pixel or external array.
8861 
8862  FixedArrayBase* elems;
8863  { MaybeObject* maybe_obj =
8864  heap->AllocateUninitializedFixedDoubleArray(capacity);
8865  if (!maybe_obj->To(&elems)) return maybe_obj;
8866  }
8867 
8868  ElementsKind elements_kind = GetElementsKind();
8869  ElementsKind new_elements_kind = elements_kind;
8870  if (IsHoleyElementsKind(elements_kind)) {
8871  new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
8872  } else {
8873  new_elements_kind = FAST_DOUBLE_ELEMENTS;
8874  }
8875 
8876  Map* new_map;
8877  { MaybeObject* maybe_obj =
8878  GetElementsTransitionMap(heap->isolate(), new_elements_kind);
8879  if (!maybe_obj->To(&new_map)) return maybe_obj;
8880  }
8881 
8882  FixedArrayBase* old_elements = elements();
8883  ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8884  { MaybeObject* maybe_obj =
8885  accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS);
8886  if (maybe_obj->IsFailure()) return maybe_obj;
8887  }
8888  if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8889  ValidateElements();
8890  set_map_and_elements(new_map, elems);
8891  } else {
8892  FixedArray* parameter_map = FixedArray::cast(old_elements);
8893  parameter_map->set(1, elems);
8894  }
8895 
8896  if (FLAG_trace_elements_transitions) {
8897  PrintElementsTransition(stdout, elements_kind, old_elements,
8898  GetElementsKind(), elems);
8899  }
8900 
8901  if (IsJSArray()) {
8902  JSArray::cast(this)->set_length(Smi::FromInt(length));
8903  }
8904 
8905  return this;
8906 }
8907 
8908 
8909 MaybeObject* JSArray::Initialize(int capacity) {
8910  Heap* heap = GetHeap();
8911  ASSERT(capacity >= 0);
8913  FixedArray* new_elements;
8914  if (capacity == 0) {
8915  new_elements = heap->empty_fixed_array();
8916  } else {
8917  MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity);
8918  if (!maybe_obj->To(&new_elements)) return maybe_obj;
8919  }
8920  set_elements(new_elements);
8921  return this;
8922 }
8923 
8924 
8925 void JSArray::Expand(int required_size) {
8927  Handle<JSArray>(this), required_size, required_size);
8928 }
8929 
8930 
8932  // We should never end in here with a pixel or external array.
8934  return GetElementsAccessor()->SetLength(this, len);
8935 }
8936 
8937 
8940  int number_of_transitions = NumberOfProtoTransitions();
8941  const int proto_offset =
8943  const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
8944  const int step = kProtoTransitionElementsPerEntry;
8945  for (int i = 0; i < number_of_transitions; i++) {
8946  if (cache->get(proto_offset + i * step) == prototype) {
8947  Object* map = cache->get(map_offset + i * step);
8948  return Map::cast(map);
8949  }
8950  }
8951  return NULL;
8952 }
8953 
8954 
8955 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
8956  ASSERT(map->IsMap());
8957  ASSERT(HeapObject::cast(prototype)->map()->IsMap());
8958  // Don't cache prototype transition if this map is shared.
8959  if (is_shared() || !FLAG_cache_prototype_transitions) return this;
8960 
8962 
8963  const int step = kProtoTransitionElementsPerEntry;
8964  const int header = kProtoTransitionHeaderSize;
8965 
8966  int capacity = (cache->length() - header) / step;
8967 
8968  int transitions = NumberOfProtoTransitions() + 1;
8969 
8970  if (transitions > capacity) {
8971  if (capacity > kMaxCachedPrototypeTransitions) return this;
8972 
8973  FixedArray* new_cache;
8974  // Grow array by factor 2 over and above what we need.
8975  { MaybeObject* maybe_cache =
8976  GetHeap()->AllocateFixedArray(transitions * 2 * step + header);
8977  if (!maybe_cache->To(&new_cache)) return maybe_cache;
8978  }
8979 
8980  for (int i = 0; i < capacity * step; i++) {
8981  new_cache->set(i + header, cache->get(i + header));
8982  }
8983  cache = new_cache;
8984  MaybeObject* set_result = SetPrototypeTransitions(cache);
8985  if (set_result->IsFailure()) return set_result;
8986  }
8987 
8988  int last = transitions - 1;
8989 
8990  cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype);
8991  cache->set(header + last * step + kProtoTransitionMapOffset, map);
8992  SetNumberOfProtoTransitions(transitions);
8993 
8994  return cache;
8995 }
8996 
8997 
8999  TransitionArray* transition_array = transitions();
9000  MemsetPointer(transition_array->data_start(),
9001  GetHeap()->the_hole_value(),
9002  transition_array->length());
9003 }
9004 
9005 
9007  FixedArray* proto_transitions = GetPrototypeTransitions();
9008  MemsetPointer(proto_transitions->data_start(),
9009  GetHeap()->the_hole_value(),
9010  proto_transitions->length());
9011 }
9012 
9013 
9014 MaybeObject* JSReceiver::SetPrototype(Object* value,
9015  bool skip_hidden_prototypes) {
9016 #ifdef DEBUG
9017  int size = Size();
9018 #endif
9019 
9020  Heap* heap = GetHeap();
9021  // Silently ignore the change if value is not a JSObject or null.
9022  // SpiderMonkey behaves this way.
9023  if (!value->IsJSReceiver() && !value->IsNull()) return value;
9024 
9025  // From 8.6.2 Object Internal Methods
9026  // ...
9027  // In addition, if [[Extensible]] is false the value of the [[Class]] and
9028  // [[Prototype]] internal properties of the object may not be modified.
9029  // ...
9030  // Implementation specific extensions that modify [[Class]], [[Prototype]]
9031  // or [[Extensible]] must not violate the invariants defined in the preceding
9032  // paragraph.
9033  if (!this->map()->is_extensible()) {
9034  HandleScope scope(heap->isolate());
9035  Handle<Object> handle(this, heap->isolate());
9036  return heap->isolate()->Throw(
9037  *FACTORY->NewTypeError("non_extensible_proto",
9038  HandleVector<Object>(&handle, 1)));
9039  }
9040 
9041  // Before we can set the prototype we need to be sure
9042  // prototype cycles are prevented.
9043  // It is sufficient to validate that the receiver is not in the new prototype
9044  // chain.
9045  for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
9046  if (JSReceiver::cast(pt) == this) {
9047  // Cycle detected.
9048  HandleScope scope(heap->isolate());
9049  return heap->isolate()->Throw(
9050  *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
9051  }
9052  }
9053 
9054  JSReceiver* real_receiver = this;
9055 
9056  if (skip_hidden_prototypes) {
9057  // Find the first object in the chain whose prototype object is not
9058  // hidden and set the new prototype on that object.
9059  Object* current_proto = real_receiver->GetPrototype();
9060  while (current_proto->IsJSObject() &&
9061  JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) {
9062  real_receiver = JSReceiver::cast(current_proto);
9063  current_proto = current_proto->GetPrototype();
9064  }
9065  }
9066 
9067  // Set the new prototype of the object.
9068  Map* map = real_receiver->map();
9069 
9070  // Nothing to do if prototype is already set.
9071  if (map->prototype() == value) return value;
9072 
9073  if (value->IsJSObject()) {
9074  MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
9075  if (ok->IsFailure()) return ok;
9076  }
9077 
9078  Map* new_map = map->GetPrototypeTransition(value);
9079  if (new_map == NULL) {
9080  MaybeObject* maybe_new_map = map->Copy();
9081  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9082 
9083  MaybeObject* maybe_new_cache =
9084  map->PutPrototypeTransition(value, new_map);
9085  if (maybe_new_cache->IsFailure()) return maybe_new_cache;
9086 
9087  new_map->set_prototype(value);
9088  }
9089  ASSERT(new_map->prototype() == value);
9090  real_receiver->set_map(new_map);
9091 
9092  heap->ClearInstanceofCache();
9093  ASSERT(size == Size());
9094  return value;
9095 }
9096 
9097 
9099  uint32_t first_arg,
9100  uint32_t arg_count,
9101  EnsureElementsMode mode) {
9102  // Elements in |Arguments| are ordered backwards (because they're on the
9103  // stack), but the method that's called here iterates over them in forward
9104  // direction.
9105  return EnsureCanContainElements(
9106  args->arguments() - first_arg - (arg_count - 1),
9107  arg_count, mode);
9108 }
9109 
9110 
9111 bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) {
9112  Isolate* isolate = GetIsolate();
9113  // Make sure that the top context does not change when doing
9114  // callbacks or interceptor calls.
9115  AssertNoContextChange ncc;
9116  HandleScope scope(isolate);
9118  Handle<JSReceiver> receiver_handle(receiver);
9119  Handle<JSObject> holder_handle(this);
9120  CustomArguments args(isolate, interceptor->data(), receiver, this);
9121  v8::AccessorInfo info(args.end());
9122  if (!interceptor->query()->IsUndefined()) {
9123  v8::IndexedPropertyQuery query =
9124  v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
9125  LOG(isolate,
9126  ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
9127  v8::Handle<v8::Integer> result;
9128  {
9129  // Leaving JavaScript.
9130  VMState state(isolate, EXTERNAL);
9131  result = query(index, info);
9132  }
9133  if (!result.IsEmpty()) {
9134  ASSERT(result->IsInt32());
9135  return true; // absence of property is signaled by empty handle.
9136  }
9137  } else if (!interceptor->getter()->IsUndefined()) {
9138  v8::IndexedPropertyGetter getter =
9139  v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
9140  LOG(isolate,
9141  ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index));
9142  v8::Handle<v8::Value> result;
9143  {
9144  // Leaving JavaScript.
9145  VMState state(isolate, EXTERNAL);
9146  result = getter(index, info);
9147  }
9148  if (!result.IsEmpty()) return true;
9149  }
9150 
9151  if (holder_handle->GetElementsAccessor()->HasElement(
9152  *receiver_handle, *holder_handle, index)) {
9153  return true;
9154  }
9155 
9156  if (holder_handle->IsStringObjectWithCharacterAt(index)) return true;
9157  Object* pt = holder_handle->GetPrototype();
9158  if (pt->IsJSProxy()) {
9159  // We need to follow the spec and simulate a call to [[GetOwnProperty]].
9161  receiver, index) != ABSENT;
9162  }
9163  if (pt->IsNull()) return false;
9164  return JSObject::cast(pt)->HasElementWithReceiver(*receiver_handle, index);
9165 }
9166 
9167 
9169  // Check access rights if needed.
9170  if (IsAccessCheckNeeded()) {
9171  Heap* heap = GetHeap();
9172  if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
9174  return UNDEFINED_ELEMENT;
9175  }
9176  }
9177 
9178  if (IsJSGlobalProxy()) {
9179  Object* proto = GetPrototype();
9180  if (proto->IsNull()) return UNDEFINED_ELEMENT;
9181  ASSERT(proto->IsJSGlobalObject());
9182  return JSObject::cast(proto)->HasLocalElement(index);
9183  }
9184 
9185  // Check for lookup interceptor
9186  if (HasIndexedInterceptor()) {
9187  return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT
9189  }
9190 
9191  // Handle [] on String objects.
9192  if (this->IsStringObjectWithCharacterAt(index)) {
9193  return STRING_CHARACTER_ELEMENT;
9194  }
9195 
9196  switch (GetElementsKind()) {
9197  case FAST_SMI_ELEMENTS:
9198  case FAST_ELEMENTS:
9200  case FAST_HOLEY_ELEMENTS: {
9201  uint32_t length = IsJSArray() ?
9202  static_cast<uint32_t>
9203  (Smi::cast(JSArray::cast(this)->length())->value()) :
9204  static_cast<uint32_t>(FixedArray::cast(elements())->length());
9205  if ((index < length) &&
9206  !FixedArray::cast(elements())->get(index)->IsTheHole()) {
9207  return FAST_ELEMENT;
9208  }
9209  break;
9210  }
9211  case FAST_DOUBLE_ELEMENTS:
9213  uint32_t length = IsJSArray() ?
9214  static_cast<uint32_t>
9215  (Smi::cast(JSArray::cast(this)->length())->value()) :
9216  static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
9217  if ((index < length) &&
9218  !FixedDoubleArray::cast(elements())->is_the_hole(index)) {
9219  return FAST_ELEMENT;
9220  }
9221  break;
9222  }
9223  case EXTERNAL_PIXEL_ELEMENTS: {
9224  ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9225  if (index < static_cast<uint32_t>(pixels->length())) return FAST_ELEMENT;
9226  break;
9227  }
9232  case EXTERNAL_INT_ELEMENTS:
9235  case EXTERNAL_DOUBLE_ELEMENTS: {
9236  ExternalArray* array = ExternalArray::cast(elements());
9237  if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT;
9238  break;
9239  }
9240  case DICTIONARY_ELEMENTS: {
9241  if (element_dictionary()->FindEntry(index) !=
9243  return DICTIONARY_ELEMENT;
9244  }
9245  break;
9246  }
9248  // Aliased parameters and non-aliased elements in a fast backing store
9249  // behave as FAST_ELEMENT. Non-aliased elements in a dictionary
9250  // backing store behave as DICTIONARY_ELEMENT.
9251  FixedArray* parameter_map = FixedArray::cast(elements());
9252  uint32_t length = parameter_map->length();
9253  Object* probe =
9254  index < (length - 2) ? parameter_map->get(index + 2) : NULL;
9255  if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
9256  // If not aliased, check the arguments.
9257  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
9258  if (arguments->IsDictionary()) {
9259  SeededNumberDictionary* dictionary =
9260  SeededNumberDictionary::cast(arguments);
9261  if (dictionary->FindEntry(index) != SeededNumberDictionary::kNotFound) {
9262  return DICTIONARY_ELEMENT;
9263  }
9264  } else {
9265  length = arguments->length();
9266  probe = (index < length) ? arguments->get(index) : NULL;
9267  if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
9268  }
9269  break;
9270  }
9271  }
9272 
9273  return UNDEFINED_ELEMENT;
9274 }
9275 
9276 
9277 bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
9278  // Check access rights if needed.
9279  if (IsAccessCheckNeeded()) {
9280  Heap* heap = GetHeap();
9281  if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
9283  return false;
9284  }
9285  }
9286 
9287  // Check for lookup interceptor
9288  if (HasIndexedInterceptor()) {
9289  return HasElementWithInterceptor(receiver, index);
9290  }
9291 
9292  ElementsAccessor* accessor = GetElementsAccessor();
9293  if (accessor->HasElement(receiver, this, index)) {
9294  return true;
9295  }
9296 
9297  // Handle [] on String objects.
9298  if (this->IsStringObjectWithCharacterAt(index)) return true;
9299 
9300  Object* pt = GetPrototype();
9301  if (pt->IsNull()) return false;
9302  if (pt->IsJSProxy()) {
9303  // We need to follow the spec and simulate a call to [[GetOwnProperty]].
9305  receiver, index) != ABSENT;
9306  }
9307  return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
9308 }
9309 
9310 
9311 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
9312  Object* value,
9313  PropertyAttributes attributes,
9314  StrictModeFlag strict_mode,
9315  bool check_prototype,
9316  SetPropertyMode set_mode) {
9317  Isolate* isolate = GetIsolate();
9318  // Make sure that the top context does not change when doing
9319  // callbacks or interceptor calls.
9320  AssertNoContextChange ncc;
9321  HandleScope scope(isolate);
9323  Handle<JSObject> this_handle(this);
9324  Handle<Object> value_handle(value, isolate);
9325  if (!interceptor->setter()->IsUndefined()) {
9326  v8::IndexedPropertySetter setter =
9327  v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
9328  LOG(isolate,
9329  ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
9330  CustomArguments args(isolate, interceptor->data(), this, this);
9331  v8::AccessorInfo info(args.end());
9332  v8::Handle<v8::Value> result;
9333  {
9334  // Leaving JavaScript.
9335  VMState state(isolate, EXTERNAL);
9336  result = setter(index, v8::Utils::ToLocal(value_handle), info);
9337  }
9339  if (!result.IsEmpty()) return *value_handle;
9340  }
9341  MaybeObject* raw_result =
9342  this_handle->SetElementWithoutInterceptor(index,
9343  *value_handle,
9344  attributes,
9345  strict_mode,
9346  check_prototype,
9347  set_mode);
9349  return raw_result;
9350 }
9351 
9352 
9353 MaybeObject* JSObject::GetElementWithCallback(Object* receiver,
9354  Object* structure,
9355  uint32_t index,
9356  Object* holder) {
9357  Isolate* isolate = GetIsolate();
9358  ASSERT(!structure->IsForeign());
9359 
9360  // api style callbacks.
9361  if (structure->IsAccessorInfo()) {
9362  Handle<AccessorInfo> data(AccessorInfo::cast(structure));
9363  Object* fun_obj = data->getter();
9364  v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
9365  if (call_fun == NULL) return isolate->heap()->undefined_value();
9366  HandleScope scope(isolate);
9367  Handle<JSObject> self(JSObject::cast(receiver));
9368  Handle<JSObject> holder_handle(JSObject::cast(holder));
9369  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9370  Handle<String> key = isolate->factory()->NumberToString(number);
9371  LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
9372  CustomArguments args(isolate, data->data(), *self, *holder_handle);
9373  v8::AccessorInfo info(args.end());
9374  v8::Handle<v8::Value> result;
9375  {
9376  // Leaving JavaScript.
9377  VMState state(isolate, EXTERNAL);
9378  result = call_fun(v8::Utils::ToLocal(key), info);
9379  }
9381  if (result.IsEmpty()) return isolate->heap()->undefined_value();
9382  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
9383  result_internal->VerifyApiCallResultType();
9384  return *result_internal;
9385  }
9386 
9387  // __defineGetter__ callback
9388  if (structure->IsAccessorPair()) {
9389  Object* getter = AccessorPair::cast(structure)->getter();
9390  if (getter->IsSpecFunction()) {
9391  // TODO(rossberg): nicer would be to cast to some JSCallable here...
9392  return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
9393  }
9394  // Getter is not a function.
9395  return isolate->heap()->undefined_value();
9396  }
9397 
9398  UNREACHABLE();
9399  return NULL;
9400 }
9401 
9402 
9403 MaybeObject* JSObject::SetElementWithCallback(Object* structure,
9404  uint32_t index,
9405  Object* value,
9406  JSObject* holder,
9407  StrictModeFlag strict_mode) {
9408  Isolate* isolate = GetIsolate();
9409  HandleScope scope(isolate);
9410 
9411  // We should never get here to initialize a const with the hole
9412  // value since a const declaration would conflict with the setter.
9413  ASSERT(!value->IsTheHole());
9414  Handle<Object> value_handle(value, isolate);
9415 
9416  // To accommodate both the old and the new api we switch on the
9417  // data structure used to store the callbacks. Eventually foreign
9418  // callbacks should be phased out.
9419  ASSERT(!structure->IsForeign());
9420 
9421  if (structure->IsAccessorInfo()) {
9422  // api style callbacks
9423  Handle<JSObject> self(this);
9424  Handle<JSObject> holder_handle(JSObject::cast(holder));
9425  Handle<AccessorInfo> data(AccessorInfo::cast(structure));
9426  Object* call_obj = data->setter();
9427  v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
9428  if (call_fun == NULL) return value;
9429  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9430  Handle<String> key(isolate->factory()->NumberToString(number));
9431  LOG(isolate, ApiNamedPropertyAccess("store", *self, *key));
9432  CustomArguments args(isolate, data->data(), *self, *holder_handle);
9433  v8::AccessorInfo info(args.end());
9434  {
9435  // Leaving JavaScript.
9436  VMState state(isolate, EXTERNAL);
9437  call_fun(v8::Utils::ToLocal(key),
9438  v8::Utils::ToLocal(value_handle),
9439  info);
9440  }
9442  return *value_handle;
9443  }
9444 
9445  if (structure->IsAccessorPair()) {
9446  Handle<Object> setter(AccessorPair::cast(structure)->setter());
9447  if (setter->IsSpecFunction()) {
9448  // TODO(rossberg): nicer would be to cast to some JSCallable here...
9449  return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value);
9450  } else {
9451  if (strict_mode == kNonStrictMode) {
9452  return value;
9453  }
9454  Handle<Object> holder_handle(holder, isolate);
9455  Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
9456  Handle<Object> args[2] = { key, holder_handle };
9457  return isolate->Throw(
9458  *isolate->factory()->NewTypeError("no_setter_in_callback",
9459  HandleVector(args, 2)));
9460  }
9461  }
9462 
9463  UNREACHABLE();
9464  return NULL;
9465 }
9466 
9467 
9469  Heap* heap = GetHeap();
9470  if (!elements()->IsFixedArray()) return false;
9471  FixedArray* elements = FixedArray::cast(this->elements());
9472  if (elements->map() != heap->non_strict_arguments_elements_map()) {
9473  return false;
9474  }
9475  FixedArray* arguments = FixedArray::cast(elements->get(1));
9476  return !arguments->IsDictionary();
9477 }
9478 
9479 
9481  Heap* heap = GetHeap();
9482  if (!elements()->IsFixedArray()) return false;
9483  FixedArray* elements = FixedArray::cast(this->elements());
9484  if (elements->map() != heap->non_strict_arguments_elements_map()) {
9485  return false;
9486  }
9487  FixedArray* arguments = FixedArray::cast(elements->get(1));
9488  return arguments->IsDictionary();
9489 }
9490 
9491 
9492 // Adding n elements in fast case is O(n*n).
9493 // Note: revisit design to have dual undefined values to capture absent
9494 // elements.
9495 MaybeObject* JSObject::SetFastElement(uint32_t index,
9496  Object* value,
9497  StrictModeFlag strict_mode,
9498  bool check_prototype) {
9501 
9502  FixedArray* backing_store = FixedArray::cast(elements());
9503  if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
9504  backing_store = FixedArray::cast(backing_store->get(1));
9505  } else {
9506  MaybeObject* maybe = EnsureWritableFastElements();
9507  if (!maybe->To(&backing_store)) return maybe;
9508  }
9509  uint32_t capacity = static_cast<uint32_t>(backing_store->length());
9510 
9511  if (check_prototype &&
9512  (index >= capacity || backing_store->get(index)->IsTheHole())) {
9513  bool found;
9514  MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9515  value,
9516  &found,
9517  strict_mode);
9518  if (found) return result;
9519  }
9520 
9521  uint32_t new_capacity = capacity;
9522  // Check if the length property of this object needs to be updated.
9523  uint32_t array_length = 0;
9524  bool must_update_array_length = false;
9525  bool introduces_holes = true;
9526  if (IsJSArray()) {
9527  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9528  introduces_holes = index > array_length;
9529  if (index >= array_length) {
9530  must_update_array_length = true;
9531  array_length = index + 1;
9532  }
9533  } else {
9534  introduces_holes = index >= capacity;
9535  }
9536 
9537  // If the array is growing, and it's not growth by a single element at the
9538  // end, make sure that the ElementsKind is HOLEY.
9539  ElementsKind elements_kind = GetElementsKind();
9540  if (introduces_holes &&
9541  IsFastElementsKind(elements_kind) &&
9542  !IsFastHoleyElementsKind(elements_kind)) {
9543  ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
9544  MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
9545  if (maybe->IsFailure()) return maybe;
9546  }
9547 
9548  // Check if the capacity of the backing store needs to be increased, or if
9549  // a transition to slow elements is necessary.
9550  if (index >= capacity) {
9551  bool convert_to_slow = true;
9552  if ((index - capacity) < kMaxGap) {
9553  new_capacity = NewElementsCapacity(index + 1);
9554  ASSERT(new_capacity > index);
9555  if (!ShouldConvertToSlowElements(new_capacity)) {
9556  convert_to_slow = false;
9557  }
9558  }
9559  if (convert_to_slow) {
9560  MaybeObject* result = NormalizeElements();
9561  if (result->IsFailure()) return result;
9562  return SetDictionaryElement(index, value, NONE, strict_mode,
9563  check_prototype);
9564  }
9565  }
9566  // Convert to fast double elements if appropriate.
9567  if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
9568  MaybeObject* maybe =
9569  SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
9570  if (maybe->IsFailure()) return maybe;
9571  FixedDoubleArray::cast(elements())->set(index, value->Number());
9572  ValidateElements();
9573  return value;
9574  }
9575  // Change elements kind from Smi-only to generic FAST if necessary.
9576  if (HasFastSmiElements() && !value->IsSmi()) {
9577  Map* new_map;
9580  : FAST_ELEMENTS;
9581  MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
9582  kind);
9583  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9584 
9585  set_map(new_map);
9586  }
9587  // Increase backing store capacity if that's been decided previously.
9588  if (new_capacity != capacity) {
9589  FixedArray* new_elements;
9591  value->IsSmi() && HasFastSmiElements()
9594  { MaybeObject* maybe =
9595  SetFastElementsCapacityAndLength(new_capacity,
9596  array_length,
9597  smi_mode);
9598  if (!maybe->To(&new_elements)) return maybe;
9599  }
9600  new_elements->set(index, value);
9601  ValidateElements();
9602  return value;
9603  }
9604 
9605  // Finally, set the new element and length.
9606  ASSERT(elements()->IsFixedArray());
9607  backing_store->set(index, value);
9608  if (must_update_array_length) {
9609  JSArray::cast(this)->set_length(Smi::FromInt(array_length));
9610  }
9611  return value;
9612 }
9613 
9614 
9615 MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
9616  Object* value,
9617  PropertyAttributes attributes,
9618  StrictModeFlag strict_mode,
9619  bool check_prototype,
9620  SetPropertyMode set_mode) {
9622  Isolate* isolate = GetIsolate();
9623  Heap* heap = isolate->heap();
9624 
9625  // Insert element in the dictionary.
9626  FixedArray* elements = FixedArray::cast(this->elements());
9627  bool is_arguments =
9628  (elements->map() == heap->non_strict_arguments_elements_map());
9629  SeededNumberDictionary* dictionary = NULL;
9630  if (is_arguments) {
9631  dictionary = SeededNumberDictionary::cast(elements->get(1));
9632  } else {
9633  dictionary = SeededNumberDictionary::cast(elements);
9634  }
9635 
9636  int entry = dictionary->FindEntry(index);
9637  if (entry != SeededNumberDictionary::kNotFound) {
9638  Object* element = dictionary->ValueAt(entry);
9639  PropertyDetails details = dictionary->DetailsAt(entry);
9640  if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
9641  return SetElementWithCallback(element, index, value, this, strict_mode);
9642  } else {
9643  dictionary->UpdateMaxNumberKey(index);
9644  // If a value has not been initialized we allow writing to it even if it
9645  // is read-only (a declared const that has not been initialized). If a
9646  // value is being defined we skip attribute checks completely.
9647  if (set_mode == DEFINE_PROPERTY) {
9648  details = PropertyDetails(
9649  attributes, NORMAL, details.dictionary_index());
9650  dictionary->DetailsAtPut(entry, details);
9651  } else if (details.IsReadOnly() && !element->IsTheHole()) {
9652  if (strict_mode == kNonStrictMode) {
9653  return isolate->heap()->undefined_value();
9654  } else {
9655  Handle<Object> holder(this);
9656  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9657  Handle<Object> args[2] = { number, holder };
9658  Handle<Object> error =
9659  isolate->factory()->NewTypeError("strict_read_only_property",
9660  HandleVector(args, 2));
9661  return isolate->Throw(*error);
9662  }
9663  }
9664  // Elements of the arguments object in slow mode might be slow aliases.
9665  if (is_arguments && element->IsAliasedArgumentsEntry()) {
9667  Context* context = Context::cast(elements->get(0));
9668  int context_index = entry->aliased_context_slot();
9669  ASSERT(!context->get(context_index)->IsTheHole());
9670  context->set(context_index, value);
9671  // For elements that are still writable we keep slow aliasing.
9672  if (!details.IsReadOnly()) value = element;
9673  }
9674  dictionary->ValueAtPut(entry, value);
9675  }
9676  } else {
9677  // Index not already used. Look for an accessor in the prototype chain.
9678  if (check_prototype) {
9679  bool found;
9680  MaybeObject* result =
9682  index, value, &found, strict_mode);
9683  if (found) return result;
9684  }
9685  // When we set the is_extensible flag to false we always force the
9686  // element into dictionary mode (and force them to stay there).
9687  if (!map()->is_extensible()) {
9688  if (strict_mode == kNonStrictMode) {
9689  return isolate->heap()->undefined_value();
9690  } else {
9691  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9692  Handle<String> name = isolate->factory()->NumberToString(number);
9693  Handle<Object> args[1] = { name };
9694  Handle<Object> error =
9695  isolate->factory()->NewTypeError("object_not_extensible",
9696  HandleVector(args, 1));
9697  return isolate->Throw(*error);
9698  }
9699  }
9700  FixedArrayBase* new_dictionary;
9701  PropertyDetails details = PropertyDetails(attributes, NORMAL);
9702  MaybeObject* maybe = dictionary->AddNumberEntry(index, value, details);
9703  if (!maybe->To(&new_dictionary)) return maybe;
9704  if (dictionary != SeededNumberDictionary::cast(new_dictionary)) {
9705  if (is_arguments) {
9706  elements->set(1, new_dictionary);
9707  } else {
9708  set_elements(new_dictionary);
9709  }
9710  dictionary = SeededNumberDictionary::cast(new_dictionary);
9711  }
9712  }
9713 
9714  // Update the array length if this JSObject is an array.
9715  if (IsJSArray()) {
9716  MaybeObject* result =
9717  JSArray::cast(this)->JSArrayUpdateLengthFromIndex(index, value);
9718  if (result->IsFailure()) return result;
9719  }
9720 
9721  // Attempt to put this object back in fast case.
9723  uint32_t new_length = 0;
9724  if (IsJSArray()) {
9725  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
9726  } else {
9727  new_length = dictionary->max_number_key() + 1;
9728  }
9729  SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays
9732  bool has_smi_only_elements = false;
9733  bool should_convert_to_fast_double_elements =
9734  ShouldConvertToFastDoubleElements(&has_smi_only_elements);
9735  if (has_smi_only_elements) {
9736  smi_mode = kForceSmiElements;
9737  }
9738  MaybeObject* result = should_convert_to_fast_double_elements
9739  ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
9740  : SetFastElementsCapacityAndLength(new_length,
9741  new_length,
9742  smi_mode);
9743  ValidateElements();
9744  if (result->IsFailure()) return result;
9745 #ifdef DEBUG
9746  if (FLAG_trace_normalization) {
9747  PrintF("Object elements are fast case again:\n");
9748  Print();
9749  }
9750 #endif
9751  }
9752  return value;
9753 }
9754 
9755 
9757  uint32_t index,
9758  Object* value,
9759  StrictModeFlag strict_mode,
9760  bool check_prototype) {
9762 
9763  FixedArrayBase* base_elms = FixedArrayBase::cast(elements());
9764  uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
9765 
9766  // If storing to an element that isn't in the array, pass the store request
9767  // up the prototype chain before storing in the receiver's elements.
9768  if (check_prototype &&
9769  (index >= elms_length ||
9770  FixedDoubleArray::cast(base_elms)->is_the_hole(index))) {
9771  bool found;
9772  MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9773  value,
9774  &found,
9775  strict_mode);
9776  if (found) return result;
9777  }
9778 
9779  // If the value object is not a heap number, switch to fast elements and try
9780  // again.
9781  bool value_is_smi = value->IsSmi();
9782  bool introduces_holes = true;
9783  uint32_t length = elms_length;
9784  if (IsJSArray()) {
9785  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9786  introduces_holes = index > length;
9787  } else {
9788  introduces_holes = index >= elms_length;
9789  }
9790 
9791  if (!value->IsNumber()) {
9792  MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
9793  elms_length,
9794  length,
9796  if (maybe_obj->IsFailure()) return maybe_obj;
9797  maybe_obj = SetFastElement(index, value, strict_mode, check_prototype);
9798  if (maybe_obj->IsFailure()) return maybe_obj;
9799  ValidateElements();
9800  return maybe_obj;
9801  }
9802 
9803  double double_value = value_is_smi
9804  ? static_cast<double>(Smi::cast(value)->value())
9805  : HeapNumber::cast(value)->value();
9806 
9807  // If the array is growing, and it's not growth by a single element at the
9808  // end, make sure that the ElementsKind is HOLEY.
9809  ElementsKind elements_kind = GetElementsKind();
9810  if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
9811  ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
9812  MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
9813  if (maybe->IsFailure()) return maybe;
9814  }
9815 
9816  // Check whether there is extra space in the fixed array.
9817  if (index < elms_length) {
9818  FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9819  elms->set(index, double_value);
9820  if (IsJSArray()) {
9821  // Update the length of the array if needed.
9822  uint32_t array_length = 0;
9823  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9824  if (index >= array_length) {
9825  JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
9826  }
9827  }
9828  return value;
9829  }
9830 
9831  // Allow gap in fast case.
9832  if ((index - elms_length) < kMaxGap) {
9833  // Try allocating extra space.
9834  int new_capacity = NewElementsCapacity(index+1);
9835  if (!ShouldConvertToSlowElements(new_capacity)) {
9836  ASSERT(static_cast<uint32_t>(new_capacity) > index);
9837  MaybeObject* maybe_obj =
9838  SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1);
9839  if (maybe_obj->IsFailure()) return maybe_obj;
9840  FixedDoubleArray::cast(elements())->set(index, double_value);
9841  ValidateElements();
9842  return value;
9843  }
9844  }
9845 
9846  // Otherwise default to slow case.
9848  ASSERT(map()->has_fast_double_elements());
9849  ASSERT(elements()->IsFixedDoubleArray());
9850  Object* obj;
9851  { MaybeObject* maybe_obj = NormalizeElements();
9852  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9853  }
9855  return SetElement(index, value, NONE, strict_mode, check_prototype);
9856 }
9857 
9858 
9859 MaybeObject* JSReceiver::SetElement(uint32_t index,
9860  Object* value,
9861  PropertyAttributes attributes,
9862  StrictModeFlag strict_mode,
9863  bool check_proto) {
9864  if (IsJSProxy()) {
9865  return JSProxy::cast(this)->SetElementWithHandler(
9866  this, index, value, strict_mode);
9867  } else {
9868  return JSObject::cast(this)->SetElement(
9869  index, value, attributes, strict_mode, check_proto);
9870  }
9871 }
9872 
9873 
9875  uint32_t index,
9876  Handle<Object> value,
9877  StrictModeFlag strict_mode) {
9878  ASSERT(!object->HasExternalArrayElements());
9880  object->GetIsolate(),
9881  object->SetElement(index, *value, NONE, strict_mode, false),
9882  Object);
9883 }
9884 
9885 
9887  uint32_t index,
9888  Handle<Object> value,
9889  PropertyAttributes attr,
9890  StrictModeFlag strict_mode,
9891  SetPropertyMode set_mode) {
9892  if (object->HasExternalArrayElements()) {
9893  if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
9894  bool has_exception;
9895  Handle<Object> number = Execution::ToNumber(value, &has_exception);
9896  if (has_exception) return Handle<Object>();
9897  value = number;
9898  }
9899  }
9901  object->GetIsolate(),
9902  object->SetElement(index, *value, attr, strict_mode, true, set_mode),
9903  Object);
9904 }
9905 
9906 
9907 MaybeObject* JSObject::SetElement(uint32_t index,
9908  Object* value,
9909  PropertyAttributes attributes,
9910  StrictModeFlag strict_mode,
9911  bool check_prototype,
9912  SetPropertyMode set_mode) {
9913  // Check access rights if needed.
9914  if (IsAccessCheckNeeded()) {
9915  Heap* heap = GetHeap();
9916  if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
9917  HandleScope scope(heap->isolate());
9918  Handle<Object> value_handle(value);
9920  return *value_handle;
9921  }
9922  }
9923 
9924  if (IsJSGlobalProxy()) {
9925  Object* proto = GetPrototype();
9926  if (proto->IsNull()) return value;
9927  ASSERT(proto->IsJSGlobalObject());
9928  return JSObject::cast(proto)->SetElement(index,
9929  value,
9930  attributes,
9931  strict_mode,
9932  check_prototype,
9933  set_mode);
9934  }
9935 
9936  // Don't allow element properties to be redefined for external arrays.
9937  if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) {
9938  Isolate* isolate = GetHeap()->isolate();
9939  Handle<Object> receiver(this);
9940  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9941  Handle<Object> args[] = { receiver, number };
9942  Handle<Object> error = isolate->factory()->NewTypeError(
9943  "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args)));
9944  return isolate->Throw(*error);
9945  }
9946 
9947  // Normalize the elements to enable attributes on the property.
9948  if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
9949  SeededNumberDictionary* dictionary;
9950  MaybeObject* maybe_object = NormalizeElements();
9951  if (!maybe_object->To(&dictionary)) return maybe_object;
9952  // Make sure that we never go back to fast case.
9953  dictionary->set_requires_slow_elements();
9954  }
9955 
9956  // Check for lookup interceptor
9957  if (HasIndexedInterceptor()) {
9958  return SetElementWithInterceptor(index,
9959  value,
9960  attributes,
9961  strict_mode,
9962  check_prototype,
9963  set_mode);
9964  }
9965 
9966  return SetElementWithoutInterceptor(index,
9967  value,
9968  attributes,
9969  strict_mode,
9970  check_prototype,
9971  set_mode);
9972 }
9973 
9974 
9975 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
9976  Object* value,
9977  PropertyAttributes attr,
9978  StrictModeFlag strict_mode,
9979  bool check_prototype,
9980  SetPropertyMode set_mode) {
9983  (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
9984  Isolate* isolate = GetIsolate();
9985  switch (GetElementsKind()) {
9986  case FAST_SMI_ELEMENTS:
9987  case FAST_ELEMENTS:
9989  case FAST_HOLEY_ELEMENTS:
9990  return SetFastElement(index, value, strict_mode, check_prototype);
9991  case FAST_DOUBLE_ELEMENTS:
9993  return SetFastDoubleElement(index, value, strict_mode, check_prototype);
9994  case EXTERNAL_PIXEL_ELEMENTS: {
9995  ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9996  return pixels->SetValue(index, value);
9997  }
9998  case EXTERNAL_BYTE_ELEMENTS: {
9999  ExternalByteArray* array = ExternalByteArray::cast(elements());
10000  return array->SetValue(index, value);
10001  }
10003  ExternalUnsignedByteArray* array =
10004  ExternalUnsignedByteArray::cast(elements());
10005  return array->SetValue(index, value);
10006  }
10007  case EXTERNAL_SHORT_ELEMENTS: {
10008  ExternalShortArray* array = ExternalShortArray::cast(elements());
10009  return array->SetValue(index, value);
10010  }
10012  ExternalUnsignedShortArray* array =
10014  return array->SetValue(index, value);
10015  }
10016  case EXTERNAL_INT_ELEMENTS: {
10017  ExternalIntArray* array = ExternalIntArray::cast(elements());
10018  return array->SetValue(index, value);
10019  }
10021  ExternalUnsignedIntArray* array =
10022  ExternalUnsignedIntArray::cast(elements());
10023  return array->SetValue(index, value);
10024  }
10025  case EXTERNAL_FLOAT_ELEMENTS: {
10026  ExternalFloatArray* array = ExternalFloatArray::cast(elements());
10027  return array->SetValue(index, value);
10028  }
10029  case EXTERNAL_DOUBLE_ELEMENTS: {
10030  ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
10031  return array->SetValue(index, value);
10032  }
10033  case DICTIONARY_ELEMENTS:
10034  return SetDictionaryElement(index, value, attr, strict_mode,
10035  check_prototype, set_mode);
10037  FixedArray* parameter_map = FixedArray::cast(elements());
10038  uint32_t length = parameter_map->length();
10039  Object* probe =
10040  (index < length - 2) ? parameter_map->get(index + 2) : NULL;
10041  if (probe != NULL && !probe->IsTheHole()) {
10042  Context* context = Context::cast(parameter_map->get(0));
10043  int context_index = Smi::cast(probe)->value();
10044  ASSERT(!context->get(context_index)->IsTheHole());
10045  context->set(context_index, value);
10046  // Redefining attributes of an aliased element destroys fast aliasing.
10047  if (set_mode == SET_PROPERTY || attr == NONE) return value;
10048  parameter_map->set_the_hole(index + 2);
10049  // For elements that are still writable we re-establish slow aliasing.
10050  if ((attr & READ_ONLY) == 0) {
10051  MaybeObject* maybe_entry =
10052  isolate->heap()->AllocateAliasedArgumentsEntry(context_index);
10053  if (!maybe_entry->ToObject(&value)) return maybe_entry;
10054  }
10055  }
10056  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
10057  if (arguments->IsDictionary()) {
10058  return SetDictionaryElement(index, value, attr, strict_mode,
10059  check_prototype, set_mode);
10060  } else {
10061  return SetFastElement(index, value, strict_mode, check_prototype);
10062  }
10063  }
10064  }
10065  // All possible cases have been handled above. Add a return to avoid the
10066  // complaints from the compiler.
10067  UNREACHABLE();
10068  return isolate->heap()->null_value();
10069 }
10070 
10071 
10073  ElementsKind to_kind) {
10074  CALL_HEAP_FUNCTION(object->GetIsolate(),
10075  object->TransitionElementsKind(to_kind),
10076  Object);
10077 }
10078 
10079 
10081  ElementsKind from_kind = map()->elements_kind();
10082 
10083  if (IsFastHoleyElementsKind(from_kind)) {
10084  to_kind = GetHoleyElementsKind(to_kind);
10085  }
10086 
10087  Isolate* isolate = GetIsolate();
10088  if (elements() == isolate->heap()->empty_fixed_array() ||
10089  (IsFastSmiOrObjectElementsKind(from_kind) &&
10090  IsFastSmiOrObjectElementsKind(to_kind)) ||
10091  (from_kind == FAST_DOUBLE_ELEMENTS &&
10092  to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
10093  ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
10094  // No change is needed to the elements() buffer, the transition
10095  // only requires a map change.
10096  MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
10097  Map* new_map;
10098  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
10099  set_map(new_map);
10100  if (FLAG_trace_elements_transitions) {
10101  FixedArrayBase* elms = FixedArrayBase::cast(elements());
10102  PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
10103  }
10104  return this;
10105  }
10106 
10107  FixedArrayBase* elms = FixedArrayBase::cast(elements());
10108  uint32_t capacity = static_cast<uint32_t>(elms->length());
10109  uint32_t length = capacity;
10110 
10111  if (IsJSArray()) {
10112  Object* raw_length = JSArray::cast(this)->length();
10113  if (raw_length->IsUndefined()) {
10114  // If length is undefined, then JSArray is being initialized and has no
10115  // elements, assume a length of zero.
10116  length = 0;
10117  } else {
10118  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
10119  }
10120  }
10121 
10122  if (IsFastSmiElementsKind(from_kind) &&
10123  IsFastDoubleElementsKind(to_kind)) {
10124  MaybeObject* maybe_result =
10125  SetFastDoubleElementsCapacityAndLength(capacity, length);
10126  if (maybe_result->IsFailure()) return maybe_result;
10127  ValidateElements();
10128  return this;
10129  }
10130 
10131  if (IsFastDoubleElementsKind(from_kind) &&
10132  IsFastObjectElementsKind(to_kind)) {
10133  MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
10134  capacity, length, kDontAllowSmiElements);
10135  if (maybe_result->IsFailure()) return maybe_result;
10136  ValidateElements();
10137  return this;
10138  }
10139 
10140  // This method should never be called for any other case than the ones
10141  // handled above.
10142  UNREACHABLE();
10143  return GetIsolate()->heap()->null_value();
10144 }
10145 
10146 
10147 // static
10149  ElementsKind to_kind) {
10150  // Transitions can't go backwards.
10151  if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
10152  return false;
10153  }
10154 
10155  // Transitions from HOLEY -> PACKED are not allowed.
10156  return !IsFastHoleyElementsKind(from_kind) ||
10157  IsFastHoleyElementsKind(to_kind);
10158 }
10159 
10160 
10161 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
10162  Object* value) {
10163  uint32_t old_len = 0;
10164  CHECK(length()->ToArrayIndex(&old_len));
10165  // Check to see if we need to update the length. For now, we make
10166  // sure that the length stays within 32-bits (unsigned).
10167  if (index >= old_len && index != 0xffffffff) {
10168  Object* len;
10169  { MaybeObject* maybe_len =
10170  GetHeap()->NumberFromDouble(static_cast<double>(index) + 1);
10171  if (!maybe_len->ToObject(&len)) return maybe_len;
10172  }
10173  set_length(len);
10174  }
10175  return value;
10176 }
10177 
10178 
10180  uint32_t index) {
10181  Isolate* isolate = GetIsolate();
10182  // Make sure that the top context does not change when doing
10183  // callbacks or interceptor calls.
10184  AssertNoContextChange ncc;
10185  HandleScope scope(isolate);
10186  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate);
10187  Handle<Object> this_handle(receiver, isolate);
10188  Handle<JSObject> holder_handle(this, isolate);
10189  if (!interceptor->getter()->IsUndefined()) {
10190  v8::IndexedPropertyGetter getter =
10191  v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
10192  LOG(isolate,
10193  ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
10194  CustomArguments args(isolate, interceptor->data(), receiver, this);
10195  v8::AccessorInfo info(args.end());
10196  v8::Handle<v8::Value> result;
10197  {
10198  // Leaving JavaScript.
10199  VMState state(isolate, EXTERNAL);
10200  result = getter(index, info);
10201  }
10203  if (!result.IsEmpty()) {
10204  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
10205  result_internal->VerifyApiCallResultType();
10206  return *result_internal;
10207  }
10208  }
10209 
10210  Heap* heap = holder_handle->GetHeap();
10211  ElementsAccessor* handler = holder_handle->GetElementsAccessor();
10212  MaybeObject* raw_result = handler->Get(*this_handle,
10213  *holder_handle,
10214  index);
10215  if (raw_result != heap->the_hole_value()) return raw_result;
10216 
10218 
10219  Object* pt = holder_handle->GetPrototype();
10220  if (pt == heap->null_value()) return heap->undefined_value();
10221  return pt->GetElementWithReceiver(*this_handle, index);
10222 }
10223 
10224 
10225 bool JSObject::HasDenseElements() {
10226  int capacity = 0;
10227  int used = 0;
10228  GetElementsCapacityAndUsage(&capacity, &used);
10229  return (capacity == 0) || (used > (capacity / 2));
10230 }
10231 
10232 
10233 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
10234  *capacity = 0;
10235  *used = 0;
10236 
10237  FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
10238  FixedArray* backing_store = NULL;
10239  switch (GetElementsKind()) {
10241  backing_store_base =
10242  FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
10243  backing_store = FixedArray::cast(backing_store_base);
10244  if (backing_store->IsDictionary()) {
10245  SeededNumberDictionary* dictionary =
10246  SeededNumberDictionary::cast(backing_store);
10247  *capacity = dictionary->Capacity();
10248  *used = dictionary->NumberOfElements();
10249  break;
10250  }
10251  // Fall through.
10252  case FAST_SMI_ELEMENTS:
10253  case FAST_ELEMENTS:
10254  if (IsJSArray()) {
10255  *capacity = backing_store_base->length();
10256  *used = Smi::cast(JSArray::cast(this)->length())->value();
10257  break;
10258  }
10259  // Fall through if packing is not guaranteed.
10261  case FAST_HOLEY_ELEMENTS:
10262  backing_store = FixedArray::cast(backing_store_base);
10263  *capacity = backing_store->length();
10264  for (int i = 0; i < *capacity; ++i) {
10265  if (!backing_store->get(i)->IsTheHole()) ++(*used);
10266  }
10267  break;
10268  case DICTIONARY_ELEMENTS: {
10269  SeededNumberDictionary* dictionary =
10271  *capacity = dictionary->Capacity();
10272  *used = dictionary->NumberOfElements();
10273  break;
10274  }
10275  case FAST_DOUBLE_ELEMENTS:
10276  if (IsJSArray()) {
10277  *capacity = backing_store_base->length();
10278  *used = Smi::cast(JSArray::cast(this)->length())->value();
10279  break;
10280  }
10281  // Fall through if packing is not guaranteed.
10283  FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
10284  *capacity = elms->length();
10285  for (int i = 0; i < *capacity; i++) {
10286  if (!elms->is_the_hole(i)) ++(*used);
10287  }
10288  break;
10289  }
10294  case EXTERNAL_INT_ELEMENTS:
10299  // External arrays are considered 100% used.
10300  ExternalArray* external_array = ExternalArray::cast(elements());
10301  *capacity = external_array->length();
10302  *used = external_array->length();
10303  break;
10304  }
10305 }
10306 
10307 
10311  if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
10312  (new_capacity <= kMaxUncheckedFastElementsLength &&
10313  GetHeap()->InNewSpace(this))) {
10314  return false;
10315  }
10316  // If the fast-case backing storage takes up roughly three times as
10317  // much space (in machine words) as a dictionary backing storage
10318  // would, the object should have slow elements.
10319  int old_capacity = 0;
10320  int used_elements = 0;
10321  GetElementsCapacityAndUsage(&old_capacity, &used_elements);
10322  int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
10324  return 3 * dictionary_size <= new_capacity;
10325 }
10326 
10327 
10330  // If the elements are sparse, we should not go back to fast case.
10331  if (!HasDenseElements()) return false;
10332  // An object requiring access checks is never allowed to have fast
10333  // elements. If it had fast elements we would skip security checks.
10334  if (IsAccessCheckNeeded()) return false;
10335 
10336  FixedArray* elements = FixedArray::cast(this->elements());
10337  SeededNumberDictionary* dictionary = NULL;
10338  if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
10339  dictionary = SeededNumberDictionary::cast(elements->get(1));
10340  } else {
10341  dictionary = SeededNumberDictionary::cast(elements);
10342  }
10343  // If an element has been added at a very high index in the elements
10344  // dictionary, we cannot go back to fast case.
10345  if (dictionary->requires_slow_elements()) return false;
10346  // If the dictionary backing storage takes up roughly half as much
10347  // space (in machine words) as a fast-case backing storage would,
10348  // the object should have fast elements.
10349  uint32_t array_size = 0;
10350  if (IsJSArray()) {
10351  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
10352  } else {
10353  array_size = dictionary->max_number_key();
10354  }
10355  uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
10357  return 2 * dictionary_size >= array_size;
10358 }
10359 
10360 
10362  bool* has_smi_only_elements) {
10363  *has_smi_only_elements = false;
10364  if (FLAG_unbox_double_arrays) {
10366  SeededNumberDictionary* dictionary =
10367  SeededNumberDictionary::cast(elements());
10368  bool found_double = false;
10369  for (int i = 0; i < dictionary->Capacity(); i++) {
10370  Object* key = dictionary->KeyAt(i);
10371  if (key->IsNumber()) {
10372  Object* value = dictionary->ValueAt(i);
10373  if (!value->IsNumber()) return false;
10374  if (!value->IsSmi()) {
10375  found_double = true;
10376  }
10377  }
10378  }
10379  *has_smi_only_elements = !found_double;
10380  return found_double;
10381  } else {
10382  return false;
10383  }
10384 }
10385 
10386 
10387 // Certain compilers request function template instantiation when they
10388 // see the definition of the other template functions in the
10389 // class. This requires us to have the template functions put
10390 // together, so even though this function belongs in objects-debug.cc,
10391 // we keep it here instead to satisfy certain compilers.
10392 #ifdef OBJECT_PRINT
10393 template<typename Shape, typename Key>
10394 void Dictionary<Shape, Key>::Print(FILE* out) {
10395  int capacity = HashTable<Shape, Key>::Capacity();
10396  for (int i = 0; i < capacity; i++) {
10399  PrintF(out, " ");
10400  if (k->IsString()) {
10401  String::cast(k)->StringPrint(out);
10402  } else {
10403  k->ShortPrint(out);
10404  }
10405  PrintF(out, ": ");
10406  ValueAt(i)->ShortPrint(out);
10407  PrintF(out, "\n");
10408  }
10409  }
10410 }
10411 #endif
10412 
10413 
10414 template<typename Shape, typename Key>
10416  int pos = 0;
10417  int capacity = HashTable<Shape, Key>::Capacity();
10418  AssertNoAllocation no_gc;
10419  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
10420  for (int i = 0; i < capacity; i++) {
10423  elements->set(pos++, ValueAt(i), mode);
10424  }
10425  }
10426  ASSERT(pos == elements->length());
10427 }
10428 
10429 
10431  ASSERT(map()->has_named_interceptor());
10432  JSFunction* constructor = JSFunction::cast(map()->constructor());
10433  ASSERT(constructor->shared()->IsApiFunction());
10434  Object* result =
10435  constructor->shared()->get_api_func_data()->named_property_handler();
10436  return InterceptorInfo::cast(result);
10437 }
10438 
10439 
10441  ASSERT(map()->has_indexed_interceptor());
10442  JSFunction* constructor = JSFunction::cast(map()->constructor());
10443  ASSERT(constructor->shared()->IsApiFunction());
10444  Object* result =
10445  constructor->shared()->get_api_func_data()->indexed_property_handler();
10446  return InterceptorInfo::cast(result);
10447 }
10448 
10449 
10451  Object* receiver,
10452  String* name,
10453  PropertyAttributes* attributes) {
10454  // Check local property in holder, ignore interceptor.
10455  LookupResult result(GetIsolate());
10456  LocalLookupRealNamedProperty(name, &result);
10457  if (result.IsFound()) {
10458  return GetProperty(receiver, &result, name, attributes);
10459  }
10460  // Continue searching via the prototype chain.
10461  Object* pt = GetPrototype();
10462  *attributes = ABSENT;
10463  if (pt->IsNull()) return GetHeap()->undefined_value();
10464  return pt->GetPropertyWithReceiver(receiver, name, attributes);
10465 }
10466 
10467 
10469  Object* receiver,
10470  String* name,
10471  PropertyAttributes* attributes) {
10472  // Check local property in holder, ignore interceptor.
10473  LookupResult result(GetIsolate());
10474  LocalLookupRealNamedProperty(name, &result);
10475  if (result.IsFound()) {
10476  return GetProperty(receiver, &result, name, attributes);
10477  }
10478  return GetHeap()->undefined_value();
10479 }
10480 
10481 
10483  Object* receiver,
10484  String* name,
10485  PropertyAttributes* attributes) {
10486  Isolate* isolate = GetIsolate();
10487  InterceptorInfo* interceptor = GetNamedInterceptor();
10488  HandleScope scope(isolate);
10489  Handle<Object> receiver_handle(receiver);
10490  Handle<JSObject> holder_handle(this);
10491  Handle<String> name_handle(name);
10492 
10493  if (!interceptor->getter()->IsUndefined()) {
10494  v8::NamedPropertyGetter getter =
10495  v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
10496  LOG(isolate,
10497  ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
10498  CustomArguments args(isolate, interceptor->data(), receiver, this);
10499  v8::AccessorInfo info(args.end());
10500  v8::Handle<v8::Value> result;
10501  {
10502  // Leaving JavaScript.
10503  VMState state(isolate, EXTERNAL);
10504  result = getter(v8::Utils::ToLocal(name_handle), info);
10505  }
10507  if (!result.IsEmpty()) {
10508  *attributes = NONE;
10509  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
10510  result_internal->VerifyApiCallResultType();
10511  return *result_internal;
10512  }
10513  }
10514 
10515  MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
10516  *receiver_handle,
10517  *name_handle,
10518  attributes);
10520  return result;
10521 }
10522 
10523 
10525  // Check access rights if needed.
10526  Isolate* isolate = GetIsolate();
10527  if (IsAccessCheckNeeded()) {
10528  if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
10529  isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10530  return false;
10531  }
10532  }
10533 
10534  LookupResult result(isolate);
10535  LocalLookupRealNamedProperty(key, &result);
10536  return result.IsFound() && !result.IsInterceptor();
10537 }
10538 
10539 
10540 bool JSObject::HasRealElementProperty(uint32_t index) {
10541  // Check access rights if needed.
10542  if (IsAccessCheckNeeded()) {
10543  Heap* heap = GetHeap();
10544  if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
10546  return false;
10547  }
10548  }
10549 
10550  // Handle [] on String objects.
10551  if (this->IsStringObjectWithCharacterAt(index)) return true;
10552 
10553  switch (GetElementsKind()) {
10554  case FAST_SMI_ELEMENTS:
10555  case FAST_ELEMENTS:
10557  case FAST_HOLEY_ELEMENTS: {
10558  uint32_t length = IsJSArray() ?
10559  static_cast<uint32_t>(
10560  Smi::cast(JSArray::cast(this)->length())->value()) :
10561  static_cast<uint32_t>(FixedArray::cast(elements())->length());
10562  return (index < length) &&
10563  !FixedArray::cast(elements())->get(index)->IsTheHole();
10564  }
10565  case FAST_DOUBLE_ELEMENTS:
10567  uint32_t length = IsJSArray() ?
10568  static_cast<uint32_t>(
10569  Smi::cast(JSArray::cast(this)->length())->value()) :
10570  static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
10571  return (index < length) &&
10572  !FixedDoubleArray::cast(elements())->is_the_hole(index);
10573  break;
10574  }
10575  case EXTERNAL_PIXEL_ELEMENTS: {
10576  ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
10577  return index < static_cast<uint32_t>(pixels->length());
10578  }
10583  case EXTERNAL_INT_ELEMENTS:
10586  case EXTERNAL_DOUBLE_ELEMENTS: {
10587  ExternalArray* array = ExternalArray::cast(elements());
10588  return index < static_cast<uint32_t>(array->length());
10589  }
10590  case DICTIONARY_ELEMENTS: {
10591  return element_dictionary()->FindEntry(index)
10593  }
10595  UNIMPLEMENTED();
10596  break;
10597  }
10598  // All possibilities have been handled above already.
10599  UNREACHABLE();
10600  return GetHeap()->null_value();
10601 }
10602 
10603 
10605  // Check access rights if needed.
10606  Isolate* isolate = GetIsolate();
10607  if (IsAccessCheckNeeded()) {
10608  if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
10609  isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10610  return false;
10611  }
10612  }
10613 
10614  LookupResult result(isolate);
10615  LocalLookupRealNamedProperty(key, &result);
10616  return result.IsPropertyCallbacks();
10617 }
10618 
10619 
10621  if (HasFastProperties()) {
10622  Map* map = this->map();
10623  if (filter == NONE) return map->NumberOfOwnDescriptors();
10624  if (filter == DONT_ENUM) {
10625  int result = map->EnumLength();
10626  if (result != Map::kInvalidEnumCache) return result;
10627  }
10628  return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
10629  }
10631 }
10632 
10633 
10634 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
10635  Object* temp = get(i);
10636  set(i, get(j));
10637  set(j, temp);
10638  if (this != numbers) {
10639  temp = numbers->get(i);
10640  numbers->set(i, Smi::cast(numbers->get(j)));
10641  numbers->set(j, Smi::cast(temp));
10642  }
10643 }
10644 
10645 
10646 static void InsertionSortPairs(FixedArray* content,
10647  FixedArray* numbers,
10648  int len) {
10649  for (int i = 1; i < len; i++) {
10650  int j = i;
10651  while (j > 0 &&
10652  (NumberToUint32(numbers->get(j - 1)) >
10653  NumberToUint32(numbers->get(j)))) {
10654  content->SwapPairs(numbers, j - 1, j);
10655  j--;
10656  }
10657  }
10658 }
10659 
10660 
10661 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
10662  // In-place heap sort.
10663  ASSERT(content->length() == numbers->length());
10664 
10665  // Bottom-up max-heap construction.
10666  for (int i = 1; i < len; ++i) {
10667  int child_index = i;
10668  while (child_index > 0) {
10669  int parent_index = ((child_index + 1) >> 1) - 1;
10670  uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
10671  uint32_t child_value = NumberToUint32(numbers->get(child_index));
10672  if (parent_value < child_value) {
10673  content->SwapPairs(numbers, parent_index, child_index);
10674  } else {
10675  break;
10676  }
10677  child_index = parent_index;
10678  }
10679  }
10680 
10681  // Extract elements and create sorted array.
10682  for (int i = len - 1; i > 0; --i) {
10683  // Put max element at the back of the array.
10684  content->SwapPairs(numbers, 0, i);
10685  // Sift down the new top element.
10686  int parent_index = 0;
10687  while (true) {
10688  int child_index = ((parent_index + 1) << 1) - 1;
10689  if (child_index >= i) break;
10690  uint32_t child1_value = NumberToUint32(numbers->get(child_index));
10691  uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
10692  uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
10693  if (child_index + 1 >= i || child1_value > child2_value) {
10694  if (parent_value > child1_value) break;
10695  content->SwapPairs(numbers, parent_index, child_index);
10696  parent_index = child_index;
10697  } else {
10698  if (parent_value > child2_value) break;
10699  content->SwapPairs(numbers, parent_index, child_index + 1);
10700  parent_index = child_index + 1;
10701  }
10702  }
10703  }
10704 }
10705 
10706 
10707 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
10708 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
10709  ASSERT(this->length() == numbers->length());
10710  // For small arrays, simply use insertion sort.
10711  if (len <= 10) {
10712  InsertionSortPairs(this, numbers, len);
10713  return;
10714  }
10715  // Check the range of indices.
10716  uint32_t min_index = NumberToUint32(numbers->get(0));
10717  uint32_t max_index = min_index;
10718  uint32_t i;
10719  for (i = 1; i < len; i++) {
10720  if (NumberToUint32(numbers->get(i)) < min_index) {
10721  min_index = NumberToUint32(numbers->get(i));
10722  } else if (NumberToUint32(numbers->get(i)) > max_index) {
10723  max_index = NumberToUint32(numbers->get(i));
10724  }
10725  }
10726  if (max_index - min_index + 1 == len) {
10727  // Indices form a contiguous range, unless there are duplicates.
10728  // Do an in-place linear time sort assuming distinct numbers, but
10729  // avoid hanging in case they are not.
10730  for (i = 0; i < len; i++) {
10731  uint32_t p;
10732  uint32_t j = 0;
10733  // While the current element at i is not at its correct position p,
10734  // swap the elements at these two positions.
10735  while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
10736  j++ < len) {
10737  SwapPairs(numbers, i, p);
10738  }
10739  }
10740  } else {
10741  HeapSortPairs(this, numbers, len);
10742  return;
10743  }
10744 }
10745 
10746 
10747 // Fill in the names of local properties into the supplied storage. The main
10748 // purpose of this function is to provide reflection information for the object
10749 // mirrors.
10750 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
10751  ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
10752  if (HasFastProperties()) {
10753  int real_size = map()->NumberOfOwnDescriptors();
10754  DescriptorArray* descs = map()->instance_descriptors();
10755  ASSERT(storage->length() >= index + real_size);
10756  for (int i = 0; i < real_size; i++) {
10757  storage->set(index + i, descs->GetKey(i));
10758  }
10759  } else {
10760  property_dictionary()->CopyKeysTo(storage,
10761  index,
10763  }
10764 }
10765 
10766 
10768  return GetLocalElementKeys(NULL, filter);
10769 }
10770 
10771 
10773  // Fast case for objects with no elements.
10774  if (!IsJSValue() && HasFastObjectElements()) {
10775  uint32_t length = IsJSArray() ?
10776  static_cast<uint32_t>(
10777  Smi::cast(JSArray::cast(this)->length())->value()) :
10778  static_cast<uint32_t>(FixedArray::cast(elements())->length());
10779  if (length == 0) return 0;
10780  }
10781  // Compute the number of enumerable elements.
10782  return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
10783 }
10784 
10785 
10787  PropertyAttributes filter) {
10788  int counter = 0;
10789  switch (GetElementsKind()) {
10790  case FAST_SMI_ELEMENTS:
10791  case FAST_ELEMENTS:
10793  case FAST_HOLEY_ELEMENTS: {
10794  int length = IsJSArray() ?
10795  Smi::cast(JSArray::cast(this)->length())->value() :
10796  FixedArray::cast(elements())->length();
10797  for (int i = 0; i < length; i++) {
10798  if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
10799  if (storage != NULL) {
10800  storage->set(counter, Smi::FromInt(i));
10801  }
10802  counter++;
10803  }
10804  }
10805  ASSERT(!storage || storage->length() >= counter);
10806  break;
10807  }
10808  case FAST_DOUBLE_ELEMENTS:
10810  int length = IsJSArray() ?
10811  Smi::cast(JSArray::cast(this)->length())->value() :
10812  FixedDoubleArray::cast(elements())->length();
10813  for (int i = 0; i < length; i++) {
10814  if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
10815  if (storage != NULL) {
10816  storage->set(counter, Smi::FromInt(i));
10817  }
10818  counter++;
10819  }
10820  }
10821  ASSERT(!storage || storage->length() >= counter);
10822  break;
10823  }
10824  case EXTERNAL_PIXEL_ELEMENTS: {
10825  int length = ExternalPixelArray::cast(elements())->length();
10826  while (counter < length) {
10827  if (storage != NULL) {
10828  storage->set(counter, Smi::FromInt(counter));
10829  }
10830  counter++;
10831  }
10832  ASSERT(!storage || storage->length() >= counter);
10833  break;
10834  }
10839  case EXTERNAL_INT_ELEMENTS:
10842  case EXTERNAL_DOUBLE_ELEMENTS: {
10843  int length = ExternalArray::cast(elements())->length();
10844  while (counter < length) {
10845  if (storage != NULL) {
10846  storage->set(counter, Smi::FromInt(counter));
10847  }
10848  counter++;
10849  }
10850  ASSERT(!storage || storage->length() >= counter);
10851  break;
10852  }
10853  case DICTIONARY_ELEMENTS: {
10854  if (storage != NULL) {
10855  element_dictionary()->CopyKeysTo(storage,
10856  filter,
10858  }
10860  break;
10861  }
10863  FixedArray* parameter_map = FixedArray::cast(elements());
10864  int mapped_length = parameter_map->length() - 2;
10865  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
10866  if (arguments->IsDictionary()) {
10867  // Copy the keys from arguments first, because Dictionary::CopyKeysTo
10868  // will insert in storage starting at index 0.
10869  SeededNumberDictionary* dictionary =
10870  SeededNumberDictionary::cast(arguments);
10871  if (storage != NULL) {
10872  dictionary->CopyKeysTo(
10873  storage, filter, SeededNumberDictionary::UNSORTED);
10874  }
10875  counter += dictionary->NumberOfElementsFilterAttributes(filter);
10876  for (int i = 0; i < mapped_length; ++i) {
10877  if (!parameter_map->get(i + 2)->IsTheHole()) {
10878  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10879  ++counter;
10880  }
10881  }
10882  if (storage != NULL) storage->SortPairs(storage, counter);
10883 
10884  } else {
10885  int backing_length = arguments->length();
10886  int i = 0;
10887  for (; i < mapped_length; ++i) {
10888  if (!parameter_map->get(i + 2)->IsTheHole()) {
10889  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10890  ++counter;
10891  } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
10892  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10893  ++counter;
10894  }
10895  }
10896  for (; i < backing_length; ++i) {
10897  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10898  ++counter;
10899  }
10900  }
10901  break;
10902  }
10903  }
10904 
10905  if (this->IsJSValue()) {
10906  Object* val = JSValue::cast(this)->value();
10907  if (val->IsString()) {
10908  String* str = String::cast(val);
10909  if (storage) {
10910  for (int i = 0; i < str->length(); i++) {
10911  storage->set(counter + i, Smi::FromInt(i));
10912  }
10913  }
10914  counter += str->length();
10915  }
10916  }
10917  ASSERT(!storage || storage->length() == counter);
10918  return counter;
10919 }
10920 
10921 
10923  return GetLocalElementKeys(storage,
10924  static_cast<PropertyAttributes>(DONT_ENUM));
10925 }
10926 
10927 
10928 // StringKey simply carries a string object as key.
10929 class StringKey : public HashTableKey {
10930  public:
10931  explicit StringKey(String* string) :
10932  string_(string),
10933  hash_(HashForObject(string)) { }
10934 
10935  bool IsMatch(Object* string) {
10936  // We know that all entries in a hash table had their hash keys created.
10937  // Use that knowledge to have fast failure.
10938  if (hash_ != HashForObject(string)) {
10939  return false;
10940  }
10941  return string_->Equals(String::cast(string));
10942  }
10943 
10944  uint32_t Hash() { return hash_; }
10945 
10946  uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
10947 
10948  Object* AsObject() { return string_; }
10949 
10951  uint32_t hash_;
10952 };
10953 
10954 
10955 // StringSharedKeys are used as keys in the eval cache.
10957  public:
10959  SharedFunctionInfo* shared,
10960  LanguageMode language_mode,
10961  int scope_position)
10962  : source_(source),
10963  shared_(shared),
10964  language_mode_(language_mode),
10965  scope_position_(scope_position) { }
10966 
10967  bool IsMatch(Object* other) {
10968  if (!other->IsFixedArray()) return false;
10969  FixedArray* other_array = FixedArray::cast(other);
10970  SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
10971  if (shared != shared_) return false;
10972  int language_unchecked = Smi::cast(other_array->get(2))->value();
10973  ASSERT(language_unchecked == CLASSIC_MODE ||
10974  language_unchecked == STRICT_MODE ||
10975  language_unchecked == EXTENDED_MODE);
10976  LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
10977  if (language_mode != language_mode_) return false;
10978  int scope_position = Smi::cast(other_array->get(3))->value();
10979  if (scope_position != scope_position_) return false;
10980  String* source = String::cast(other_array->get(1));
10981  return source->Equals(source_);
10982  }
10983 
10984  static uint32_t StringSharedHashHelper(String* source,
10985  SharedFunctionInfo* shared,
10986  LanguageMode language_mode,
10987  int scope_position) {
10988  uint32_t hash = source->Hash();
10989  if (shared->HasSourceCode()) {
10990  // Instead of using the SharedFunctionInfo pointer in the hash
10991  // code computation, we use a combination of the hash of the
10992  // script source code and the start position of the calling scope.
10993  // We do this to ensure that the cache entries can survive garbage
10994  // collection.
10995  Script* script = Script::cast(shared->script());
10996  hash ^= String::cast(script->source())->Hash();
10997  if (language_mode == STRICT_MODE) hash ^= 0x8000;
10998  if (language_mode == EXTENDED_MODE) hash ^= 0x0080;
10999  hash += scope_position;
11000  }
11001  return hash;
11002  }
11003 
11004  uint32_t Hash() {
11005  return StringSharedHashHelper(
11006  source_, shared_, language_mode_, scope_position_);
11007  }
11008 
11009  uint32_t HashForObject(Object* obj) {
11010  FixedArray* other_array = FixedArray::cast(obj);
11011  SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
11012  String* source = String::cast(other_array->get(1));
11013  int language_unchecked = Smi::cast(other_array->get(2))->value();
11014  ASSERT(language_unchecked == CLASSIC_MODE ||
11015  language_unchecked == STRICT_MODE ||
11016  language_unchecked == EXTENDED_MODE);
11017  LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
11018  int scope_position = Smi::cast(other_array->get(3))->value();
11019  return StringSharedHashHelper(
11020  source, shared, language_mode, scope_position);
11021  }
11022 
11023  MUST_USE_RESULT MaybeObject* AsObject() {
11024  Object* obj;
11025  { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(4);
11026  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11027  }
11028  FixedArray* other_array = FixedArray::cast(obj);
11029  other_array->set(0, shared_);
11030  other_array->set(1, source_);
11031  other_array->set(2, Smi::FromInt(language_mode_));
11032  other_array->set(3, Smi::FromInt(scope_position_));
11033  return other_array;
11034  }
11035 
11036  private:
11037  String* source_;
11038  SharedFunctionInfo* shared_;
11039  LanguageMode language_mode_;
11040  int scope_position_;
11041 };
11042 
11043 
11044 // RegExpKey carries the source and flags of a regular expression as key.
11045 class RegExpKey : public HashTableKey {
11046  public:
11048  : string_(string),
11049  flags_(Smi::FromInt(flags.value())) { }
11050 
11051  // Rather than storing the key in the hash table, a pointer to the
11052  // stored value is stored where the key should be. IsMatch then
11053  // compares the search key to the found object, rather than comparing
11054  // a key to a key.
11055  bool IsMatch(Object* obj) {
11056  FixedArray* val = FixedArray::cast(obj);
11058  && (flags_ == val->get(JSRegExp::kFlagsIndex));
11059  }
11060 
11061  uint32_t Hash() { return RegExpHash(string_, flags_); }
11062 
11064  // Plain hash maps, which is where regexp keys are used, don't
11065  // use this function.
11066  UNREACHABLE();
11067  return NULL;
11068  }
11069 
11070  uint32_t HashForObject(Object* obj) {
11071  FixedArray* val = FixedArray::cast(obj);
11074  }
11075 
11076  static uint32_t RegExpHash(String* string, Smi* flags) {
11077  return string->Hash() + flags->value();
11078  }
11079 
11082 };
11083 
11084 // Utf8SymbolKey carries a vector of chars as key.
11085 class Utf8SymbolKey : public HashTableKey {
11086  public:
11087  explicit Utf8SymbolKey(Vector<const char> string, uint32_t seed)
11088  : string_(string), hash_field_(0), seed_(seed) { }
11089 
11090  bool IsMatch(Object* string) {
11091  return String::cast(string)->IsEqualTo(string_);
11092  }
11093 
11094  uint32_t Hash() {
11095  if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
11097  static_cast<unsigned>(string_.length()));
11098  chars_ = buffer.Utf16Length();
11100  uint32_t result = hash_field_ >> String::kHashShift;
11101  ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
11102  return result;
11103  }
11104 
11105  uint32_t HashForObject(Object* other) {
11106  return String::cast(other)->Hash();
11107  }
11108 
11109  MaybeObject* AsObject() {
11110  if (hash_field_ == 0) Hash();
11111  return Isolate::Current()->heap()->AllocateSymbol(
11113  }
11114 
11116  uint32_t hash_field_;
11117  int chars_; // Caches the number of characters when computing the hash code.
11118  uint32_t seed_;
11119 };
11120 
11121 
11122 template <typename Char>
11124  public:
11125  explicit SequentialSymbolKey(Vector<const Char> string, uint32_t seed)
11126  : string_(string), hash_field_(0), seed_(seed) { }
11127 
11128  uint32_t Hash() {
11129  StringHasher hasher(string_.length(), seed_);
11130 
11131  // Very long strings have a trivial hash that doesn't inspect the
11132  // string contents.
11133  if (hasher.has_trivial_hash()) {
11134  hash_field_ = hasher.GetHashField();
11135  } else {
11136  int i = 0;
11137  // Do the iterative array index computation as long as there is a
11138  // chance this is an array index.
11139  while (i < string_.length() && hasher.is_array_index()) {
11140  hasher.AddCharacter(static_cast<uc32>(string_[i]));
11141  i++;
11142  }
11143 
11144  // Process the remaining characters without updating the array
11145  // index.
11146  while (i < string_.length()) {
11147  hasher.AddCharacterNoIndex(static_cast<uc32>(string_[i]));
11148  i++;
11149  }
11150  hash_field_ = hasher.GetHashField();
11151  }
11152 
11153  uint32_t result = hash_field_ >> String::kHashShift;
11154  ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
11155  return result;
11156  }
11157 
11158 
11159  uint32_t HashForObject(Object* other) {
11160  return String::cast(other)->Hash();
11161  }
11162 
11164  uint32_t hash_field_;
11165  uint32_t seed_;
11166 };
11167 
11168 
11169 
11170 class AsciiSymbolKey : public SequentialSymbolKey<char> {
11171  public:
11173  : SequentialSymbolKey<char>(str, seed) { }
11174 
11175  bool IsMatch(Object* string) {
11176  return String::cast(string)->IsAsciiEqualTo(string_);
11177  }
11178 
11179  MaybeObject* AsObject() {
11180  if (hash_field_ == 0) Hash();
11181  return HEAP->AllocateAsciiSymbol(string_, hash_field_);
11182  }
11183 };
11184 
11185 
11187  public:
11189  int from,
11190  int length,
11191  uint32_t seed)
11192  : string_(string), from_(from), length_(length), seed_(seed) { }
11193 
11194  uint32_t Hash() {
11195  ASSERT(length_ >= 0);
11196  ASSERT(from_ + length_ <= string_->length());
11197  StringHasher hasher(length_, string_->GetHeap()->HashSeed());
11198 
11199  // Very long strings have a trivial hash that doesn't inspect the
11200  // string contents.
11201  if (hasher.has_trivial_hash()) {
11202  hash_field_ = hasher.GetHashField();
11203  } else {
11204  int i = 0;
11205  // Do the iterative array index computation as long as there is a
11206  // chance this is an array index.
11207  while (i < length_ && hasher.is_array_index()) {
11208  hasher.AddCharacter(static_cast<uc32>(
11209  string_->SeqAsciiStringGet(i + from_)));
11210  i++;
11211  }
11212 
11213  // Process the remaining characters without updating the array
11214  // index.
11215  while (i < length_) {
11216  hasher.AddCharacterNoIndex(static_cast<uc32>(
11217  string_->SeqAsciiStringGet(i + from_)));
11218  i++;
11219  }
11220  hash_field_ = hasher.GetHashField();
11221  }
11222 
11223  uint32_t result = hash_field_ >> String::kHashShift;
11224  ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
11225  return result;
11226  }
11227 
11228 
11229  uint32_t HashForObject(Object* other) {
11230  return String::cast(other)->Hash();
11231  }
11232 
11233  bool IsMatch(Object* string) {
11234  Vector<const char> chars(string_->GetChars() + from_, length_);
11235  return String::cast(string)->IsAsciiEqualTo(chars);
11236  }
11237 
11238  MaybeObject* AsObject() {
11239  if (hash_field_ == 0) Hash();
11240  Vector<const char> chars(string_->GetChars() + from_, length_);
11241  return HEAP->AllocateAsciiSymbol(chars, hash_field_);
11242  }
11243 
11244  private:
11245  Handle<SeqAsciiString> string_;
11246  int from_;
11247  int length_;
11248  uint32_t hash_field_;
11249  uint32_t seed_;
11250 };
11251 
11252 
11254  public:
11255  explicit TwoByteSymbolKey(Vector<const uc16> str, uint32_t seed)
11256  : SequentialSymbolKey<uc16>(str, seed) { }
11257 
11258  bool IsMatch(Object* string) {
11259  return String::cast(string)->IsTwoByteEqualTo(string_);
11260  }
11261 
11262  MaybeObject* AsObject() {
11263  if (hash_field_ == 0) Hash();
11264  return HEAP->AllocateTwoByteSymbol(string_, hash_field_);
11265  }
11266 };
11267 
11268 
11269 // SymbolKey carries a string/symbol object as key.
11270 class SymbolKey : public HashTableKey {
11271  public:
11272  explicit SymbolKey(String* string)
11273  : string_(string) { }
11274 
11275  bool IsMatch(Object* string) {
11276  return String::cast(string)->Equals(string_);
11277  }
11278 
11279  uint32_t Hash() { return string_->Hash(); }
11280 
11281  uint32_t HashForObject(Object* other) {
11282  return String::cast(other)->Hash();
11283  }
11284 
11285  MaybeObject* AsObject() {
11286  // Attempt to flatten the string, so that symbols will most often
11287  // be flat strings.
11289  Heap* heap = string_->GetHeap();
11290  // Transform string to symbol if possible.
11291  Map* map = heap->SymbolMapForString(string_);
11292  if (map != NULL) {
11294  ASSERT(string_->IsSymbol());
11295  return string_;
11296  }
11297  // Otherwise allocate a new symbol.
11298  StringInputBuffer buffer(string_);
11299  return heap->AllocateInternalSymbol(&buffer,
11300  string_->length(),
11301  string_->hash_field());
11302  }
11303 
11304  static uint32_t StringHash(Object* obj) {
11305  return String::cast(obj)->Hash();
11306  }
11307 
11309 };
11310 
11311 
11312 template<typename Shape, typename Key>
11314  IteratePointers(v, 0, kElementsStartOffset);
11315 }
11316 
11317 
11318 template<typename Shape, typename Key>
11320  IteratePointers(v,
11321  kElementsStartOffset,
11322  kHeaderSize + length() * kPointerSize);
11323 }
11324 
11325 
11326 template<typename Shape, typename Key>
11327 MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for,
11328  MinimumCapacity capacity_option,
11329  PretenureFlag pretenure) {
11330  ASSERT(!capacity_option || IS_POWER_OF_TWO(at_least_space_for));
11331  int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
11332  ? at_least_space_for
11333  : ComputeCapacity(at_least_space_for);
11334  if (capacity > HashTable::kMaxCapacity) {
11336  }
11337 
11338  Object* obj;
11339  { MaybeObject* maybe_obj = Isolate::Current()->heap()->
11340  AllocateHashTable(EntryToIndex(capacity), pretenure);
11341  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11342  }
11345  HashTable::cast(obj)->SetCapacity(capacity);
11346  return obj;
11347 }
11348 
11349 
11350 // Find entry for key otherwise return kNotFound.
11352  if (!key->IsSymbol()) {
11354  }
11355 
11356  // Optimized for symbol key. Knowledge of the key type allows:
11357  // 1. Move the check if the key is a symbol out of the loop.
11358  // 2. Avoid comparing hash codes in symbol to symbol comparison.
11359  // 3. Detect a case when a dictionary key is not a symbol but the key is.
11360  // In case of positive result the dictionary key may be replaced by
11361  // the symbol with minimal performance penalty. It gives a chance to
11362  // perform further lookups in code stubs (and significant performance boost
11363  // a certain style of code).
11364 
11365  // EnsureCapacity will guarantee the hash table is never full.
11366  uint32_t capacity = Capacity();
11367  uint32_t entry = FirstProbe(key->Hash(), capacity);
11368  uint32_t count = 1;
11369 
11370  while (true) {
11371  int index = EntryToIndex(entry);
11372  Object* element = get(index);
11373  if (element->IsUndefined()) break; // Empty entry.
11374  if (key == element) return entry;
11375  if (!element->IsSymbol() &&
11376  !element->IsTheHole() &&
11377  String::cast(element)->Equals(key)) {
11378  // Replace a non-symbol key by the equivalent symbol for faster further
11379  // lookups.
11380  set(index, key);
11381  return entry;
11382  }
11383  ASSERT(element->IsTheHole() || !String::cast(element)->Equals(key));
11384  entry = NextProbe(entry, count++, capacity);
11385  }
11386  return kNotFound;
11387 }
11388 
11389 
11390 template<typename Shape, typename Key>
11391 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) {
11392  ASSERT(NumberOfElements() < new_table->Capacity());
11393 
11394  AssertNoAllocation no_gc;
11395  WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
11396 
11397  // Copy prefix to new array.
11398  for (int i = kPrefixStartIndex;
11399  i < kPrefixStartIndex + Shape::kPrefixSize;
11400  i++) {
11401  new_table->set(i, get(i), mode);
11402  }
11403 
11404  // Rehash the elements.
11405  int capacity = Capacity();
11406  for (int i = 0; i < capacity; i++) {
11407  uint32_t from_index = EntryToIndex(i);
11408  Object* k = get(from_index);
11409  if (IsKey(k)) {
11410  uint32_t hash = HashTable<Shape, Key>::HashForObject(key, k);
11411  uint32_t insertion_index =
11412  EntryToIndex(new_table->FindInsertionEntry(hash));
11413  for (int j = 0; j < Shape::kEntrySize; j++) {
11414  new_table->set(insertion_index + j, get(from_index + j), mode);
11415  }
11416  }
11417  }
11418  new_table->SetNumberOfElements(NumberOfElements());
11419  new_table->SetNumberOfDeletedElements(0);
11420  return new_table;
11421 }
11422 
11423 
11424 template<typename Shape, typename Key>
11425 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
11426  int capacity = Capacity();
11427  int nof = NumberOfElements() + n;
11428  int nod = NumberOfDeletedElements();
11429  // Return if:
11430  // 50% is still free after adding n elements and
11431  // at most 50% of the free elements are deleted elements.
11432  if (nod <= (capacity - nof) >> 1) {
11433  int needed_free = nof >> 1;
11434  if (nof + needed_free <= capacity) return this;
11435  }
11436 
11437  const int kMinCapacityForPretenure = 256;
11438  bool pretenure =
11439  (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this);
11440  Object* obj;
11441  { MaybeObject* maybe_obj =
11442  Allocate(nof * 2,
11443  USE_DEFAULT_MINIMUM_CAPACITY,
11444  pretenure ? TENURED : NOT_TENURED);
11445  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11446  }
11447 
11448  return Rehash(HashTable::cast(obj), key);
11449 }
11450 
11451 
11452 template<typename Shape, typename Key>
11453 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) {
11454  int capacity = Capacity();
11455  int nof = NumberOfElements();
11456 
11457  // Shrink to fit the number of elements if only a quarter of the
11458  // capacity is filled with elements.
11459  if (nof > (capacity >> 2)) return this;
11460  // Allocate a new dictionary with room for at least the current
11461  // number of elements. The allocation method will make sure that
11462  // there is extra room in the dictionary for additions. Don't go
11463  // lower than room for 16 elements.
11464  int at_least_room_for = nof;
11465  if (at_least_room_for < 16) return this;
11466 
11467  const int kMinCapacityForPretenure = 256;
11468  bool pretenure =
11469  (at_least_room_for > kMinCapacityForPretenure) &&
11470  !GetHeap()->InNewSpace(this);
11471  Object* obj;
11472  { MaybeObject* maybe_obj =
11473  Allocate(at_least_room_for,
11474  USE_DEFAULT_MINIMUM_CAPACITY,
11475  pretenure ? TENURED : NOT_TENURED);
11476  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11477  }
11478 
11479  return Rehash(HashTable::cast(obj), key);
11480 }
11481 
11482 
11483 template<typename Shape, typename Key>
11485  uint32_t capacity = Capacity();
11486  uint32_t entry = FirstProbe(hash, capacity);
11487  uint32_t count = 1;
11488  // EnsureCapacity will guarantee the hash table is never full.
11489  while (true) {
11490  Object* element = KeyAt(entry);
11491  if (element->IsUndefined() || element->IsTheHole()) break;
11492  entry = NextProbe(entry, count++, capacity);
11493  }
11494  return entry;
11495 }
11496 
11497 // Force instantiation of template instances class.
11498 // Please note this list is compiler dependent.
11499 
11501 
11503 
11505 
11506 template class HashTable<ObjectHashTableShape<1>, Object*>;
11507 
11508 template class HashTable<ObjectHashTableShape<2>, Object*>;
11509 
11511 
11513 
11515 
11517  Allocate(int at_least_space_for);
11518 
11520  Allocate(int at_least_space_for);
11521 
11523  int);
11524 
11526  uint32_t, Object*);
11527 
11529  AtPut(uint32_t, Object*);
11530 
11532  SlowReverseLookup(Object* value);
11533 
11535  SlowReverseLookup(Object* value);
11536 
11538  Object*);
11539 
11541  FixedArray*,
11544 
11546  int, JSObject::DeleteMode);
11547 
11550 
11552  String*);
11553 
11555  uint32_t);
11556 
11558  FixedArray*,
11559  int,
11561 
11562 template int
11565 
11567  String*, Object*, PropertyDetails);
11568 
11569 template MaybeObject*
11571 
11572 template int
11575 
11577  uint32_t, Object*, PropertyDetails);
11578 
11580  uint32_t, Object*, PropertyDetails);
11581 
11583  EnsureCapacity(int, uint32_t);
11584 
11586  EnsureCapacity(int, uint32_t);
11587 
11589  EnsureCapacity(int, String*);
11590 
11592  AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
11593 
11595  AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
11596 
11598  String*, Object*, PropertyDetails, uint32_t);
11599 
11600 template
11602 
11603 template
11605 
11606 template
11608 
11609 
11610 // Collates undefined and unexisting elements below limit from position
11611 // zero of the elements. The object stays in Dictionary mode.
11612 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
11614  // Must stay in dictionary mode, either because of requires_slow_elements,
11615  // or because we are not going to sort (and therefore compact) all of the
11616  // elements.
11618  HeapNumber* result_double = NULL;
11619  if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
11620  // Allocate space for result before we start mutating the object.
11621  Object* new_double;
11622  { MaybeObject* maybe_new_double = GetHeap()->AllocateHeapNumber(0.0);
11623  if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
11624  }
11625  result_double = HeapNumber::cast(new_double);
11626  }
11627 
11628  Object* obj;
11629  { MaybeObject* maybe_obj =
11631  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11632  }
11634 
11635  AssertNoAllocation no_alloc;
11636 
11637  uint32_t pos = 0;
11638  uint32_t undefs = 0;
11639  int capacity = dict->Capacity();
11640  for (int i = 0; i < capacity; i++) {
11641  Object* k = dict->KeyAt(i);
11642  if (dict->IsKey(k)) {
11643  ASSERT(k->IsNumber());
11644  ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
11645  ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
11646  ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
11647  Object* value = dict->ValueAt(i);
11648  PropertyDetails details = dict->DetailsAt(i);
11649  if (details.type() == CALLBACKS) {
11650  // Bail out and do the sorting of undefineds and array holes in JS.
11651  return Smi::FromInt(-1);
11652  }
11653  uint32_t key = NumberToUint32(k);
11654  // In the following we assert that adding the entry to the new dictionary
11655  // does not cause GC. This is the case because we made sure to allocate
11656  // the dictionary big enough above, so it need not grow.
11657  if (key < limit) {
11658  if (value->IsUndefined()) {
11659  undefs++;
11660  } else {
11661  if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
11662  // Adding an entry with the key beyond smi-range requires
11663  // allocation. Bailout.
11664  return Smi::FromInt(-1);
11665  }
11666  new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked();
11667  pos++;
11668  }
11669  } else {
11670  if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
11671  // Adding an entry with the key beyond smi-range requires
11672  // allocation. Bailout.
11673  return Smi::FromInt(-1);
11674  }
11675  new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
11676  }
11677  }
11678  }
11679 
11680  uint32_t result = pos;
11681  PropertyDetails no_details = PropertyDetails(NONE, NORMAL);
11682  Heap* heap = GetHeap();
11683  while (undefs > 0) {
11684  if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
11685  // Adding an entry with the key beyond smi-range requires
11686  // allocation. Bailout.
11687  return Smi::FromInt(-1);
11688  }
11689  new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
11690  ToObjectUnchecked();
11691  pos++;
11692  undefs--;
11693  }
11694 
11695  set_elements(new_dict);
11696 
11697  if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
11698  return Smi::FromInt(static_cast<int>(result));
11699  }
11700 
11701  ASSERT_NE(NULL, result_double);
11702  result_double->set_value(static_cast<double>(result));
11703  return result_double;
11704 }
11705 
11706 
11707 // Collects all defined (non-hole) and non-undefined (array) elements at
11708 // the start of the elements array.
11709 // If the object is in dictionary mode, it is converted to fast elements
11710 // mode.
11711 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
11712  Heap* heap = GetHeap();
11713 
11714  if (HasDictionaryElements()) {
11715  // Convert to fast elements containing only the existing properties.
11716  // Ordering is irrelevant, since we are going to sort anyway.
11718  if (IsJSArray() || dict->requires_slow_elements() ||
11719  dict->max_number_key() >= limit) {
11720  return PrepareSlowElementsForSort(limit);
11721  }
11722  // Convert to fast elements.
11723 
11724  Object* obj;
11725  MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
11727  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11728  Map* new_map = Map::cast(obj);
11729 
11730  PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
11731  Object* new_array;
11732  { MaybeObject* maybe_new_array =
11733  heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
11734  if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
11735  }
11736  FixedArray* fast_elements = FixedArray::cast(new_array);
11737  dict->CopyValuesTo(fast_elements);
11738  ValidateElements();
11739 
11740  set_map_and_elements(new_map, fast_elements);
11741  } else if (HasExternalArrayElements()) {
11742  // External arrays cannot have holes or undefined elements.
11743  return Smi::FromInt(ExternalArray::cast(elements())->length());
11744  } else if (!HasFastDoubleElements()) {
11745  Object* obj;
11746  { MaybeObject* maybe_obj = EnsureWritableFastElements();
11747  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11748  }
11749  }
11751 
11752  // Collect holes at the end, undefined before that and the rest at the
11753  // start, and return the number of non-hole, non-undefined values.
11754 
11755  FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
11756  uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
11757  if (limit > elements_length) {
11758  limit = elements_length ;
11759  }
11760  if (limit == 0) {
11761  return Smi::FromInt(0);
11762  }
11763 
11764  HeapNumber* result_double = NULL;
11765  if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
11766  // Pessimistically allocate space for return value before
11767  // we start mutating the array.
11768  Object* new_double;
11769  { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0);
11770  if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
11771  }
11772  result_double = HeapNumber::cast(new_double);
11773  }
11774 
11775  uint32_t result = 0;
11776  if (elements_base->map() == heap->fixed_double_array_map()) {
11777  FixedDoubleArray* elements = FixedDoubleArray::cast(elements_base);
11778  // Split elements into defined and the_hole, in that order.
11779  unsigned int holes = limit;
11780  // Assume most arrays contain no holes and undefined values, so minimize the
11781  // number of stores of non-undefined, non-the-hole values.
11782  for (unsigned int i = 0; i < holes; i++) {
11783  if (elements->is_the_hole(i)) {
11784  holes--;
11785  } else {
11786  continue;
11787  }
11788  // Position i needs to be filled.
11789  while (holes > i) {
11790  if (elements->is_the_hole(holes)) {
11791  holes--;
11792  } else {
11793  elements->set(i, elements->get_scalar(holes));
11794  break;
11795  }
11796  }
11797  }
11798  result = holes;
11799  while (holes < limit) {
11800  elements->set_the_hole(holes);
11801  holes++;
11802  }
11803  } else {
11804  FixedArray* elements = FixedArray::cast(elements_base);
11805  AssertNoAllocation no_alloc;
11806 
11807  // Split elements into defined, undefined and the_hole, in that order. Only
11808  // count locations for undefined and the hole, and fill them afterwards.
11809  WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc);
11810  unsigned int undefs = limit;
11811  unsigned int holes = limit;
11812  // Assume most arrays contain no holes and undefined values, so minimize the
11813  // number of stores of non-undefined, non-the-hole values.
11814  for (unsigned int i = 0; i < undefs; i++) {
11815  Object* current = elements->get(i);
11816  if (current->IsTheHole()) {
11817  holes--;
11818  undefs--;
11819  } else if (current->IsUndefined()) {
11820  undefs--;
11821  } else {
11822  continue;
11823  }
11824  // Position i needs to be filled.
11825  while (undefs > i) {
11826  current = elements->get(undefs);
11827  if (current->IsTheHole()) {
11828  holes--;
11829  undefs--;
11830  } else if (current->IsUndefined()) {
11831  undefs--;
11832  } else {
11833  elements->set(i, current, write_barrier);
11834  break;
11835  }
11836  }
11837  }
11838  result = undefs;
11839  while (undefs < holes) {
11840  elements->set_undefined(undefs);
11841  undefs++;
11842  }
11843  while (holes < limit) {
11844  elements->set_the_hole(holes);
11845  holes++;
11846  }
11847  }
11848 
11849  if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
11850  return Smi::FromInt(static_cast<int>(result));
11851  }
11852  ASSERT_NE(NULL, result_double);
11853  result_double->set_value(static_cast<double>(result));
11854  return result_double;
11855 }
11856 
11857 
11858 Object* ExternalPixelArray::SetValue(uint32_t index, Object* value) {
11859  uint8_t clamped_value = 0;
11860  if (index < static_cast<uint32_t>(length())) {
11861  if (value->IsSmi()) {
11862  int int_value = Smi::cast(value)->value();
11863  if (int_value < 0) {
11864  clamped_value = 0;
11865  } else if (int_value > 255) {
11866  clamped_value = 255;
11867  } else {
11868  clamped_value = static_cast<uint8_t>(int_value);
11869  }
11870  } else if (value->IsHeapNumber()) {
11871  double double_value = HeapNumber::cast(value)->value();
11872  if (!(double_value > 0)) {
11873  // NaN and less than zero clamp to zero.
11874  clamped_value = 0;
11875  } else if (double_value > 255) {
11876  // Greater than 255 clamp to 255.
11877  clamped_value = 255;
11878  } else {
11879  // Other doubles are rounded to the nearest integer.
11880  clamped_value = static_cast<uint8_t>(lrint(double_value));
11881  }
11882  } else {
11883  // Clamp undefined to zero (default). All other types have been
11884  // converted to a number type further up in the call chain.
11885  ASSERT(value->IsUndefined());
11886  }
11887  set(index, clamped_value);
11888  }
11889  return Smi::FromInt(clamped_value);
11890 }
11891 
11892 
11893 template<typename ExternalArrayClass, typename ValueType>
11894 static MaybeObject* ExternalArrayIntSetter(Heap* heap,
11895  ExternalArrayClass* receiver,
11896  uint32_t index,
11897  Object* value) {
11898  ValueType cast_value = 0;
11899  if (index < static_cast<uint32_t>(receiver->length())) {
11900  if (value->IsSmi()) {
11901  int int_value = Smi::cast(value)->value();
11902  cast_value = static_cast<ValueType>(int_value);
11903  } else if (value->IsHeapNumber()) {
11904  double double_value = HeapNumber::cast(value)->value();
11905  cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
11906  } else {
11907  // Clamp undefined to zero (default). All other types have been
11908  // converted to a number type further up in the call chain.
11909  ASSERT(value->IsUndefined());
11910  }
11911  receiver->set(index, cast_value);
11912  }
11913  return heap->NumberFromInt32(cast_value);
11914 }
11915 
11916 
11917 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) {
11918  return ExternalArrayIntSetter<ExternalByteArray, int8_t>
11919  (GetHeap(), this, index, value);
11920 }
11921 
11922 
11923 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index,
11924  Object* value) {
11925  return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t>
11926  (GetHeap(), this, index, value);
11927 }
11928 
11929 
11930 MaybeObject* ExternalShortArray::SetValue(uint32_t index,
11931  Object* value) {
11932  return ExternalArrayIntSetter<ExternalShortArray, int16_t>
11933  (GetHeap(), this, index, value);
11934 }
11935 
11936 
11937 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index,
11938  Object* value) {
11939  return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t>
11940  (GetHeap(), this, index, value);
11941 }
11942 
11943 
11944 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) {
11945  return ExternalArrayIntSetter<ExternalIntArray, int32_t>
11946  (GetHeap(), this, index, value);
11947 }
11948 
11949 
11950 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) {
11951  uint32_t cast_value = 0;
11952  Heap* heap = GetHeap();
11953  if (index < static_cast<uint32_t>(length())) {
11954  if (value->IsSmi()) {
11955  int int_value = Smi::cast(value)->value();
11956  cast_value = static_cast<uint32_t>(int_value);
11957  } else if (value->IsHeapNumber()) {
11958  double double_value = HeapNumber::cast(value)->value();
11959  cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
11960  } else {
11961  // Clamp undefined to zero (default). All other types have been
11962  // converted to a number type further up in the call chain.
11963  ASSERT(value->IsUndefined());
11964  }
11965  set(index, cast_value);
11966  }
11967  return heap->NumberFromUint32(cast_value);
11968 }
11969 
11970 
11971 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) {
11972  float cast_value = static_cast<float>(OS::nan_value());
11973  Heap* heap = GetHeap();
11974  if (index < static_cast<uint32_t>(length())) {
11975  if (value->IsSmi()) {
11976  int int_value = Smi::cast(value)->value();
11977  cast_value = static_cast<float>(int_value);
11978  } else if (value->IsHeapNumber()) {
11979  double double_value = HeapNumber::cast(value)->value();
11980  cast_value = static_cast<float>(double_value);
11981  } else {
11982  // Clamp undefined to NaN (default). All other types have been
11983  // converted to a number type further up in the call chain.
11984  ASSERT(value->IsUndefined());
11985  }
11986  set(index, cast_value);
11987  }
11988  return heap->AllocateHeapNumber(cast_value);
11989 }
11990 
11991 
11992 MaybeObject* ExternalDoubleArray::SetValue(uint32_t index, Object* value) {
11993  double double_value = OS::nan_value();
11994  Heap* heap = GetHeap();
11995  if (index < static_cast<uint32_t>(length())) {
11996  if (value->IsSmi()) {
11997  int int_value = Smi::cast(value)->value();
11998  double_value = static_cast<double>(int_value);
11999  } else if (value->IsHeapNumber()) {
12000  double_value = HeapNumber::cast(value)->value();
12001  } else {
12002  // Clamp undefined to NaN (default). All other types have been
12003  // converted to a number type further up in the call chain.
12004  ASSERT(value->IsUndefined());
12005  }
12006  set(index, double_value);
12007  }
12008  return heap->AllocateHeapNumber(double_value);
12009 }
12010 
12011 
12014  Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
12015  return JSGlobalPropertyCell::cast(value);
12016 }
12017 
12018 
12020  Handle<GlobalObject> global,
12021  Handle<String> name) {
12022  Isolate* isolate = global->GetIsolate();
12023  CALL_HEAP_FUNCTION(isolate,
12024  global->EnsurePropertyCell(*name),
12026 }
12027 
12028 
12031  int entry = property_dictionary()->FindEntry(name);
12032  if (entry == StringDictionary::kNotFound) {
12033  Heap* heap = GetHeap();
12034  Object* cell;
12035  { MaybeObject* maybe_cell =
12036  heap->AllocateJSGlobalPropertyCell(heap->the_hole_value());
12037  if (!maybe_cell->ToObject(&cell)) return maybe_cell;
12038  }
12039  PropertyDetails details(NONE, NORMAL);
12040  details = details.AsDeleted();
12041  Object* dictionary;
12042  { MaybeObject* maybe_dictionary =
12043  property_dictionary()->Add(name, cell, details);
12044  if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary;
12045  }
12046  set_properties(StringDictionary::cast(dictionary));
12047  return cell;
12048  } else {
12049  Object* value = property_dictionary()->ValueAt(entry);
12050  ASSERT(value->IsJSGlobalPropertyCell());
12051  return value;
12052  }
12053 }
12054 
12055 
12056 MaybeObject* SymbolTable::LookupString(String* string, Object** s) {
12057  SymbolKey key(string);
12058  return LookupKey(&key, s);
12059 }
12060 
12061 
12062 // This class is used for looking up two character strings in the symbol table.
12063 // If we don't have a hit we don't want to waste much time so we unroll the
12064 // string hash calculation loop here for speed. Doesn't work if the two
12065 // characters form a decimal integer, since such strings have a different hash
12066 // algorithm.
12068  public:
12069  TwoCharHashTableKey(uint32_t c1, uint32_t c2, uint32_t seed)
12070  : c1_(c1), c2_(c2) {
12071  // Char 1.
12072  uint32_t hash = seed;
12073  hash += c1;
12074  hash += hash << 10;
12075  hash ^= hash >> 6;
12076  // Char 2.
12077  hash += c2;
12078  hash += hash << 10;
12079  hash ^= hash >> 6;
12080  // GetHash.
12081  hash += hash << 3;
12082  hash ^= hash >> 11;
12083  hash += hash << 15;
12084  if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
12085 #ifdef DEBUG
12086  StringHasher hasher(2, seed);
12087  hasher.AddCharacter(c1);
12088  hasher.AddCharacter(c2);
12089  // If this assert fails then we failed to reproduce the two-character
12090  // version of the string hashing algorithm above. One reason could be
12091  // that we were passed two digits as characters, since the hash
12092  // algorithm is different in that case.
12093  ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash));
12094 #endif
12095  hash_ = hash;
12096  }
12097 
12098  bool IsMatch(Object* o) {
12099  if (!o->IsString()) return false;
12100  String* other = String::cast(o);
12101  if (other->length() != 2) return false;
12102  if (other->Get(0) != c1_) return false;
12103  return other->Get(1) == c2_;
12104  }
12105 
12106  uint32_t Hash() { return hash_; }
12107  uint32_t HashForObject(Object* key) {
12108  if (!key->IsString()) return 0;
12109  return String::cast(key)->Hash();
12110  }
12111 
12112  Object* AsObject() {
12113  // The TwoCharHashTableKey is only used for looking in the symbol
12114  // table, not for adding to it.
12115  UNREACHABLE();
12116  return NULL;
12117  }
12118 
12119  private:
12120  uint32_t c1_;
12121  uint32_t c2_;
12122  uint32_t hash_;
12123 };
12124 
12125 
12127  SymbolKey key(string);
12128  int entry = FindEntry(&key);
12129  if (entry == kNotFound) {
12130  return false;
12131  } else {
12132  String* result = String::cast(KeyAt(entry));
12133  ASSERT(StringShape(result).IsSymbol());
12134  *symbol = result;
12135  return true;
12136  }
12137 }
12138 
12139 
12141  uint32_t c2,
12142  String** symbol) {
12143  TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed());
12144  int entry = FindEntry(&key);
12145  if (entry == kNotFound) {
12146  return false;
12147  } else {
12148  String* result = String::cast(KeyAt(entry));
12149  ASSERT(StringShape(result).IsSymbol());
12150  *symbol = result;
12151  return true;
12152  }
12153 }
12154 
12155 
12157  Object** s) {
12158  Utf8SymbolKey key(str, GetHeap()->HashSeed());
12159  return LookupKey(&key, s);
12160 }
12161 
12162 
12164  Object** s) {
12165  AsciiSymbolKey key(str, GetHeap()->HashSeed());
12166  return LookupKey(&key, s);
12167 }
12168 
12169 
12171  int from,
12172  int length,
12173  Object** s) {
12174  SubStringAsciiSymbolKey key(str, from, length, GetHeap()->HashSeed());
12175  return LookupKey(&key, s);
12176 }
12177 
12178 
12180  Object** s) {
12181  TwoByteSymbolKey key(str, GetHeap()->HashSeed());
12182  return LookupKey(&key, s);
12183 }
12184 
12185 MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
12186  int entry = FindEntry(key);
12187 
12188  // Symbol already in table.
12189  if (entry != kNotFound) {
12190  *s = KeyAt(entry);
12191  return this;
12192  }
12193 
12194  // Adding new symbol. Grow table if needed.
12195  Object* obj;
12196  { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12197  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12198  }
12199 
12200  // Create symbol object.
12201  Object* symbol;
12202  { MaybeObject* maybe_symbol = key->AsObject();
12203  if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol;
12204  }
12205 
12206  // If the symbol table grew as part of EnsureCapacity, obj is not
12207  // the current symbol table and therefore we cannot use
12208  // SymbolTable::cast here.
12209  SymbolTable* table = reinterpret_cast<SymbolTable*>(obj);
12210 
12211  // Add the new symbol and return it along with the symbol table.
12212  entry = table->FindInsertionEntry(key->Hash());
12213  table->set(EntryToIndex(entry), symbol);
12214  table->ElementAdded();
12215  *s = symbol;
12216  return table;
12217 }
12218 
12219 
12220 // The key for the script compilation cache is dependent on the mode flags,
12221 // because they change the global language mode and thus binding behaviour.
12222 // If flags change at some point, we must ensure that we do not hit the cache
12223 // for code compiled with different settings.
12224 static LanguageMode CurrentGlobalLanguageMode() {
12225  return FLAG_use_strict
12226  ? (FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE)
12227  : CLASSIC_MODE;
12228 }
12229 
12230 
12232  SharedFunctionInfo* shared = context->closure()->shared();
12233  StringSharedKey key(src,
12234  shared,
12235  CurrentGlobalLanguageMode(),
12236  RelocInfo::kNoPosition);
12237  int entry = FindEntry(&key);
12238  if (entry == kNotFound) return GetHeap()->undefined_value();
12239  return get(EntryToIndex(entry) + 1);
12240 }
12241 
12242 
12244  Context* context,
12245  LanguageMode language_mode,
12246  int scope_position) {
12247  StringSharedKey key(src,
12248  context->closure()->shared(),
12249  language_mode,
12250  scope_position);
12251  int entry = FindEntry(&key);
12252  if (entry == kNotFound) return GetHeap()->undefined_value();
12253  return get(EntryToIndex(entry) + 1);
12254 }
12255 
12256 
12258  JSRegExp::Flags flags) {
12259  RegExpKey key(src, flags);
12260  int entry = FindEntry(&key);
12261  if (entry == kNotFound) return GetHeap()->undefined_value();
12262  return get(EntryToIndex(entry) + 1);
12263 }
12264 
12265 
12267  Context* context,
12268  Object* value) {
12269  SharedFunctionInfo* shared = context->closure()->shared();
12270  StringSharedKey key(src,
12271  shared,
12272  CurrentGlobalLanguageMode(),
12273  RelocInfo::kNoPosition);
12274  CompilationCacheTable* cache;
12275  MaybeObject* maybe_cache = EnsureCapacity(1, &key);
12276  if (!maybe_cache->To(&cache)) return maybe_cache;
12277 
12278  Object* k;
12279  MaybeObject* maybe_k = key.AsObject();
12280  if (!maybe_k->To(&k)) return maybe_k;
12281 
12282  int entry = cache->FindInsertionEntry(key.Hash());
12283  cache->set(EntryToIndex(entry), k);
12284  cache->set(EntryToIndex(entry) + 1, value);
12285  cache->ElementAdded();
12286  return cache;
12287 }
12288 
12289 
12291  Context* context,
12292  SharedFunctionInfo* value,
12293  int scope_position) {
12294  StringSharedKey key(src,
12295  context->closure()->shared(),
12296  value->language_mode(),
12297  scope_position);
12298  Object* obj;
12299  { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
12300  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12301  }
12302 
12303  CompilationCacheTable* cache =
12304  reinterpret_cast<CompilationCacheTable*>(obj);
12305  int entry = cache->FindInsertionEntry(key.Hash());
12306 
12307  Object* k;
12308  { MaybeObject* maybe_k = key.AsObject();
12309  if (!maybe_k->ToObject(&k)) return maybe_k;
12310  }
12311 
12312  cache->set(EntryToIndex(entry), k);
12313  cache->set(EntryToIndex(entry) + 1, value);
12314  cache->ElementAdded();
12315  return cache;
12316 }
12317 
12318 
12320  JSRegExp::Flags flags,
12321  FixedArray* value) {
12322  RegExpKey key(src, flags);
12323  Object* obj;
12324  { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
12325  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12326  }
12327 
12328  CompilationCacheTable* cache =
12329  reinterpret_cast<CompilationCacheTable*>(obj);
12330  int entry = cache->FindInsertionEntry(key.Hash());
12331  // We store the value in the key slot, and compare the search key
12332  // to the stored value with a custon IsMatch function during lookups.
12333  cache->set(EntryToIndex(entry), value);
12334  cache->set(EntryToIndex(entry) + 1, value);
12335  cache->ElementAdded();
12336  return cache;
12337 }
12338 
12339 
12340 void CompilationCacheTable::Remove(Object* value) {
12341  Object* the_hole_value = GetHeap()->the_hole_value();
12342  for (int entry = 0, size = Capacity(); entry < size; entry++) {
12343  int entry_index = EntryToIndex(entry);
12344  int value_index = entry_index + 1;
12345  if (get(value_index) == value) {
12346  NoWriteBarrierSet(this, entry_index, the_hole_value);
12347  NoWriteBarrierSet(this, value_index, the_hole_value);
12348  ElementRemoved();
12349  }
12350  }
12351  return;
12352 }
12353 
12354 
12355 // SymbolsKey used for HashTable where key is array of symbols.
12356 class SymbolsKey : public HashTableKey {
12357  public:
12358  explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { }
12359 
12360  bool IsMatch(Object* symbols) {
12361  FixedArray* o = FixedArray::cast(symbols);
12362  int len = symbols_->length();
12363  if (o->length() != len) return false;
12364  for (int i = 0; i < len; i++) {
12365  if (o->get(i) != symbols_->get(i)) return false;
12366  }
12367  return true;
12368  }
12369 
12370  uint32_t Hash() { return HashForObject(symbols_); }
12371 
12372  uint32_t HashForObject(Object* obj) {
12373  FixedArray* symbols = FixedArray::cast(obj);
12374  int len = symbols->length();
12375  uint32_t hash = 0;
12376  for (int i = 0; i < len; i++) {
12377  hash ^= String::cast(symbols->get(i))->Hash();
12378  }
12379  return hash;
12380  }
12381 
12382  Object* AsObject() { return symbols_; }
12383 
12384  private:
12385  FixedArray* symbols_;
12386 };
12387 
12388 
12389 Object* MapCache::Lookup(FixedArray* array) {
12390  SymbolsKey key(array);
12391  int entry = FindEntry(&key);
12392  if (entry == kNotFound) return GetHeap()->undefined_value();
12393  return get(EntryToIndex(entry) + 1);
12394 }
12395 
12396 
12397 MaybeObject* MapCache::Put(FixedArray* array, Map* value) {
12398  SymbolsKey key(array);
12399  Object* obj;
12400  { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
12401  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12402  }
12403 
12404  MapCache* cache = reinterpret_cast<MapCache*>(obj);
12405  int entry = cache->FindInsertionEntry(key.Hash());
12406  cache->set(EntryToIndex(entry), array);
12407  cache->set(EntryToIndex(entry) + 1, value);
12408  cache->ElementAdded();
12409  return cache;
12410 }
12411 
12412 
12413 template<typename Shape, typename Key>
12414 MaybeObject* Dictionary<Shape, Key>::Allocate(int at_least_space_for) {
12415  Object* obj;
12416  { MaybeObject* maybe_obj =
12417  HashTable<Shape, Key>::Allocate(at_least_space_for);
12418  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12419  }
12420  // Initialize the next enumeration index.
12422  SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
12423  return obj;
12424 }
12425 
12426 
12428  Handle<StringDictionary> dictionary) {
12429  CALL_HEAP_FUNCTION_VOID(dictionary->GetIsolate(),
12430  dictionary->GenerateNewEnumerationIndices());
12431 }
12432 
12433 template<typename Shape, typename Key>
12437 
12438  // Allocate and initialize iteration order array.
12439  Object* obj;
12440  { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12441  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12442  }
12443  FixedArray* iteration_order = FixedArray::cast(obj);
12444  for (int i = 0; i < length; i++) {
12445  iteration_order->set(i, Smi::FromInt(i));
12446  }
12447 
12448  // Allocate array with enumeration order.
12449  { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12450  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12451  }
12452  FixedArray* enumeration_order = FixedArray::cast(obj);
12453 
12454  // Fill the enumeration order array with property details.
12455  int capacity = HashTable<Shape, Key>::Capacity();
12456  int pos = 0;
12457  for (int i = 0; i < capacity; i++) {
12459  int index = DetailsAt(i).dictionary_index();
12460  enumeration_order->set(pos++, Smi::FromInt(index));
12461  }
12462  }
12463 
12464  // Sort the arrays wrt. enumeration order.
12465  iteration_order->SortPairs(enumeration_order, enumeration_order->length());
12466 
12467  // Overwrite the enumeration_order with the enumeration indices.
12468  for (int i = 0; i < length; i++) {
12469  int index = Smi::cast(iteration_order->get(i))->value();
12470  int enum_index = PropertyDetails::kInitialIndex + i;
12471  enumeration_order->set(index, Smi::FromInt(enum_index));
12472  }
12473 
12474  // Update the dictionary with new indices.
12475  capacity = HashTable<Shape, Key>::Capacity();
12476  pos = 0;
12477  for (int i = 0; i < capacity; i++) {
12479  int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
12480  PropertyDetails details = DetailsAt(i);
12481  PropertyDetails new_details =
12482  PropertyDetails(details.attributes(), details.type(), enum_index);
12483  DetailsAtPut(i, new_details);
12484  }
12485  }
12486 
12487  // Set the next enumeration index.
12488  SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
12489  return this;
12490 }
12491 
12492 template<typename Shape, typename Key>
12493 MaybeObject* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
12494  // Check whether there are enough enumeration indices to add n elements.
12495  if (Shape::kIsEnumerable &&
12496  !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
12497  // If not, we generate new indices for the properties.
12498  Object* result;
12499  { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
12500  if (!maybe_result->ToObject(&result)) return maybe_result;
12501  }
12502  }
12504 }
12505 
12506 
12507 template<typename Shape, typename Key>
12509  JSReceiver::DeleteMode mode) {
12511  PropertyDetails details = DetailsAt(entry);
12512  // Ignore attributes if forcing a deletion.
12513  if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
12514  return heap->false_value();
12515  }
12516  SetEntry(entry, heap->the_hole_value(), heap->the_hole_value());
12518  return heap->true_value();
12519 }
12520 
12521 
12522 template<typename Shape, typename Key>
12523 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) {
12524  return HashTable<Shape, Key>::Shrink(key);
12525 }
12526 
12527 
12528 template<typename Shape, typename Key>
12529 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
12530  int entry = this->FindEntry(key);
12531 
12532  // If the entry is present set the value;
12533  if (entry != Dictionary<Shape, Key>::kNotFound) {
12534  ValueAtPut(entry, value);
12535  return this;
12536  }
12537 
12538  // Check whether the dictionary should be extended.
12539  Object* obj;
12540  { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12541  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12542  }
12543 
12544  Object* k;
12545  { MaybeObject* maybe_k = Shape::AsObject(key);
12546  if (!maybe_k->ToObject(&k)) return maybe_k;
12547  }
12548  PropertyDetails details = PropertyDetails(NONE, NORMAL);
12549 
12550  return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
12552 }
12553 
12554 
12555 template<typename Shape, typename Key>
12556 MaybeObject* Dictionary<Shape, Key>::Add(Key key,
12557  Object* value,
12558  PropertyDetails details) {
12559  ASSERT(details.dictionary_index() == details.descriptor_index());
12560 
12561  // Valdate key is absent.
12562  SLOW_ASSERT((this->FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
12563  // Check whether the dictionary should be extended.
12564  Object* obj;
12565  { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12566  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12567  }
12568 
12569  return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
12571 }
12572 
12573 
12574 // Add a key, value pair to the dictionary.
12575 template<typename Shape, typename Key>
12577  Object* value,
12578  PropertyDetails details,
12579  uint32_t hash) {
12580  // Compute the key object.
12581  Object* k;
12582  { MaybeObject* maybe_k = Shape::AsObject(key);
12583  if (!maybe_k->ToObject(&k)) return maybe_k;
12584  }
12585 
12586  uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
12587  // Insert element at empty or deleted entry
12588  if (!details.IsDeleted() &&
12589  details.dictionary_index() == 0 &&
12590  Shape::kIsEnumerable) {
12591  // Assign an enumeration index to the property and update
12592  // SetNextEnumerationIndex.
12593  int index = NextEnumerationIndex();
12594  details = PropertyDetails(details.attributes(), details.type(), index);
12595  SetNextEnumerationIndex(index + 1);
12596  }
12597  SetEntry(entry, k, value, details);
12598  ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
12599  || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
12601  return this;
12602 }
12603 
12604 
12606  // If the dictionary requires slow elements an element has already
12607  // been added at a high index.
12608  if (requires_slow_elements()) return;
12609  // Check if this index is high enough that we should require slow
12610  // elements.
12611  if (key > kRequiresSlowElementsLimit) {
12613  return;
12614  }
12615  // Update max key value.
12616  Object* max_index_object = get(kMaxNumberKeyIndex);
12617  if (!max_index_object->IsSmi() || max_number_key() < key) {
12620  }
12621 }
12622 
12623 
12624 MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key,
12625  Object* value,
12626  PropertyDetails details) {
12627  UpdateMaxNumberKey(key);
12628  SLOW_ASSERT(this->FindEntry(key) == kNotFound);
12629  return Add(key, value, details);
12630 }
12631 
12632 
12634  Object* value) {
12635  SLOW_ASSERT(this->FindEntry(key) == kNotFound);
12636  return Add(key, value, PropertyDetails(NONE, NORMAL));
12637 }
12638 
12639 
12640 MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) {
12641  UpdateMaxNumberKey(key);
12642  return AtPut(key, value);
12643 }
12644 
12645 
12646 MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key,
12647  Object* value) {
12648  return AtPut(key, value);
12649 }
12650 
12651 
12653  Handle<SeededNumberDictionary> dictionary,
12654  uint32_t index,
12655  Handle<Object> value,
12656  PropertyDetails details) {
12657  CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
12658  dictionary->Set(index, *value, details),
12660 }
12661 
12662 
12665  uint32_t index,
12666  Handle<Object> value) {
12667  CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
12668  dictionary->Set(index, *value),
12670 }
12671 
12672 
12673 MaybeObject* SeededNumberDictionary::Set(uint32_t key,
12674  Object* value,
12675  PropertyDetails details) {
12676  int entry = FindEntry(key);
12677  if (entry == kNotFound) return AddNumberEntry(key, value, details);
12678  // Preserve enumeration index.
12679  details = PropertyDetails(details.attributes(),
12680  details.type(),
12681  DetailsAt(entry).dictionary_index());
12682  MaybeObject* maybe_object_key = SeededNumberDictionaryShape::AsObject(key);
12683  Object* object_key;
12684  if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
12685  SetEntry(entry, object_key, value, details);
12686  return this;
12687 }
12688 
12689 
12690 MaybeObject* UnseededNumberDictionary::Set(uint32_t key,
12691  Object* value) {
12692  int entry = FindEntry(key);
12693  if (entry == kNotFound) return AddNumberEntry(key, value);
12694  MaybeObject* maybe_object_key = UnseededNumberDictionaryShape::AsObject(key);
12695  Object* object_key;
12696  if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
12697  SetEntry(entry, object_key, value);
12698  return this;
12699 }
12700 
12701 
12702 
12703 template<typename Shape, typename Key>
12705  PropertyAttributes filter) {
12706  int capacity = HashTable<Shape, Key>::Capacity();
12707  int result = 0;
12708  for (int i = 0; i < capacity; i++) {
12709  Object* k = HashTable<Shape, Key>::KeyAt(i);
12711  PropertyDetails details = DetailsAt(i);
12712  if (details.IsDeleted()) continue;
12713  PropertyAttributes attr = details.attributes();
12714  if ((attr & filter) == 0) result++;
12715  }
12716  }
12717  return result;
12718 }
12719 
12720 
12721 template<typename Shape, typename Key>
12723  return NumberOfElementsFilterAttributes(
12724  static_cast<PropertyAttributes>(DONT_ENUM));
12725 }
12726 
12727 
12728 template<typename Shape, typename Key>
12730  FixedArray* storage,
12731  PropertyAttributes filter,
12732  typename Dictionary<Shape, Key>::SortMode sort_mode) {
12733  ASSERT(storage->length() >= NumberOfEnumElements());
12734  int capacity = HashTable<Shape, Key>::Capacity();
12735  int index = 0;
12736  for (int i = 0; i < capacity; i++) {
12737  Object* k = HashTable<Shape, Key>::KeyAt(i);
12739  PropertyDetails details = DetailsAt(i);
12740  if (details.IsDeleted()) continue;
12741  PropertyAttributes attr = details.attributes();
12742  if ((attr & filter) == 0) storage->set(index++, k);
12743  }
12744  }
12745  if (sort_mode == Dictionary<Shape, Key>::SORTED) {
12746  storage->SortPairs(storage, index);
12747  }
12748  ASSERT(storage->length() >= index);
12749 }
12750 
12751 
12753  int length = storage->length();
12754  ASSERT(length >= NumberOfEnumElements());
12755  Heap* heap = GetHeap();
12756  Object* undefined_value = heap->undefined_value();
12757  int capacity = Capacity();
12758  int properties = 0;
12759 
12760  // Fill in the enumeration array by assigning enumerable keys at their
12761  // enumeration index. This will leave holes in the array if there are keys
12762  // that are deleted or not enumerable.
12763  for (int i = 0; i < capacity; i++) {
12764  Object* k = KeyAt(i);
12765  if (IsKey(k)) {
12766  PropertyDetails details = DetailsAt(i);
12767  if (details.IsDeleted() || details.IsDontEnum()) continue;
12768  properties++;
12769  storage->set(details.dictionary_index() - 1, k);
12770  if (properties == length) break;
12771  }
12772  }
12773 
12774  // There are holes in the enumeration array if less properties were assigned
12775  // than the length of the array. If so, crunch all the existing properties
12776  // together by shifting them to the left (maintaining the enumeration order),
12777  // and trimming of the right side of the array.
12778  if (properties < length) {
12779  if (properties == 0) return heap->empty_fixed_array();
12780  properties = 0;
12781  for (int i = 0; i < length; ++i) {
12782  Object* value = storage->get(i);
12783  if (value != undefined_value) {
12784  storage->set(properties, value);
12785  ++properties;
12786  }
12787  }
12788  RightTrimFixedArray<FROM_MUTATOR>(heap, storage, length - properties);
12789  }
12790  return storage;
12791 }
12792 
12793 
12794 template<typename Shape, typename Key>
12796  FixedArray* storage,
12797  int index,
12798  typename Dictionary<Shape, Key>::SortMode sort_mode) {
12799  ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
12800  static_cast<PropertyAttributes>(NONE)));
12801  int capacity = HashTable<Shape, Key>::Capacity();
12802  for (int i = 0; i < capacity; i++) {
12803  Object* k = HashTable<Shape, Key>::KeyAt(i);
12805  PropertyDetails details = DetailsAt(i);
12806  if (details.IsDeleted()) continue;
12807  storage->set(index++, k);
12808  }
12809  }
12810  if (sort_mode == Dictionary<Shape, Key>::SORTED) {
12811  storage->SortPairs(storage, index);
12812  }
12813  ASSERT(storage->length() >= index);
12814 }
12815 
12816 
12817 // Backwards lookup (slow).
12818 template<typename Shape, typename Key>
12820  int capacity = HashTable<Shape, Key>::Capacity();
12821  for (int i = 0; i < capacity; i++) {
12822  Object* k = HashTable<Shape, Key>::KeyAt(i);
12824  Object* e = ValueAt(i);
12825  if (e->IsJSGlobalPropertyCell()) {
12826  e = JSGlobalPropertyCell::cast(e)->value();
12827  }
12828  if (e == value) return k;
12829  }
12830  }
12832  return heap->undefined_value();
12833 }
12834 
12835 
12837  JSObject* obj, int unused_property_fields) {
12838  // Make sure we preserve dictionary representation if there are too many
12839  // descriptors.
12840  int number_of_elements = NumberOfElements();
12841  if (number_of_elements > DescriptorArray::kMaxNumberOfDescriptors) return obj;
12842 
12843  if (number_of_elements != NextEnumerationIndex()) {
12844  MaybeObject* maybe_result = GenerateNewEnumerationIndices();
12845  if (maybe_result->IsFailure()) return maybe_result;
12846  }
12847 
12848  int instance_descriptor_length = 0;
12849  int number_of_fields = 0;
12850 
12851  Heap* heap = GetHeap();
12852 
12853  // Compute the length of the instance descriptor.
12854  int capacity = Capacity();
12855  for (int i = 0; i < capacity; i++) {
12856  Object* k = KeyAt(i);
12857  if (IsKey(k)) {
12858  Object* value = ValueAt(i);
12859  PropertyType type = DetailsAt(i).type();
12860  ASSERT(type != FIELD);
12861  instance_descriptor_length++;
12862  if (type == NORMAL &&
12863  (!value->IsJSFunction() || heap->InNewSpace(value))) {
12864  number_of_fields += 1;
12865  }
12866  }
12867  }
12868 
12869  int inobject_props = obj->map()->inobject_properties();
12870 
12871  // Allocate new map.
12872  Map* new_map;
12873  MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
12874  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
12875  new_map->set_dictionary_map(false);
12876 
12877  if (instance_descriptor_length == 0) {
12878  ASSERT_LE(unused_property_fields, inobject_props);
12879  // Transform the object.
12880  new_map->set_unused_property_fields(inobject_props);
12881  obj->set_map(new_map);
12882  obj->set_properties(heap->empty_fixed_array());
12883  // Check that it really works.
12884  ASSERT(obj->HasFastProperties());
12885  return obj;
12886  }
12887 
12888  // Allocate the instance descriptor.
12889  DescriptorArray* descriptors;
12890  MaybeObject* maybe_descriptors =
12891  DescriptorArray::Allocate(instance_descriptor_length);
12892  if (!maybe_descriptors->To(&descriptors)) {
12893  return maybe_descriptors;
12894  }
12895 
12896  DescriptorArray::WhitenessWitness witness(descriptors);
12897 
12898  int number_of_allocated_fields =
12899  number_of_fields + unused_property_fields - inobject_props;
12900  if (number_of_allocated_fields < 0) {
12901  // There is enough inobject space for all fields (including unused).
12902  number_of_allocated_fields = 0;
12903  unused_property_fields = inobject_props - number_of_fields;
12904  }
12905 
12906  // Allocate the fixed array for the fields.
12907  FixedArray* fields;
12908  MaybeObject* maybe_fields =
12909  heap->AllocateFixedArray(number_of_allocated_fields);
12910  if (!maybe_fields->To(&fields)) return maybe_fields;
12911 
12912  // Fill in the instance descriptor and the fields.
12913  int current_offset = 0;
12914  for (int i = 0; i < capacity; i++) {
12915  Object* k = KeyAt(i);
12916  if (IsKey(k)) {
12917  Object* value = ValueAt(i);
12918  // Ensure the key is a symbol before writing into the instance descriptor.
12919  String* key;
12920  MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k));
12921  if (!maybe_key->To(&key)) return maybe_key;
12922 
12923  PropertyDetails details = DetailsAt(i);
12924  ASSERT(details.descriptor_index() == details.dictionary_index());
12925  int enumeration_index = details.descriptor_index();
12926  PropertyType type = details.type();
12927 
12928  if (value->IsJSFunction() && !heap->InNewSpace(value)) {
12930  JSFunction::cast(value),
12931  details.attributes(),
12932  enumeration_index);
12933  descriptors->Set(enumeration_index - 1, &d, witness);
12934  } else if (type == NORMAL) {
12935  if (current_offset < inobject_props) {
12936  obj->InObjectPropertyAtPut(current_offset,
12937  value,
12939  } else {
12940  int offset = current_offset - inobject_props;
12941  fields->set(offset, value);
12942  }
12943  FieldDescriptor d(key,
12944  current_offset++,
12945  details.attributes(),
12946  enumeration_index);
12947  descriptors->Set(enumeration_index - 1, &d, witness);
12948  } else if (type == CALLBACKS) {
12949  CallbacksDescriptor d(key,
12950  value,
12951  details.attributes(),
12952  enumeration_index);
12953  descriptors->Set(enumeration_index - 1, &d, witness);
12954  } else {
12955  UNREACHABLE();
12956  }
12957  }
12958  }
12959  ASSERT(current_offset == number_of_fields);
12960 
12961  descriptors->Sort();
12962 
12963  new_map->InitializeDescriptors(descriptors);
12964  new_map->set_unused_property_fields(unused_property_fields);
12965 
12966  // Transform the object.
12967  obj->set_map(new_map);
12968 
12969  obj->set_properties(fields);
12970  ASSERT(obj->IsJSObject());
12971 
12972  // Check that it really works.
12973  ASSERT(obj->HasFastProperties());
12974 
12975  return obj;
12976 }
12977 
12978 
12979 bool ObjectHashSet::Contains(Object* key) {
12980  ASSERT(IsKey(key));
12981 
12982  // If the object does not have an identity hash, it was never used as a key.
12983  { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12984  if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return false;
12985  }
12986  return (FindEntry(key) != kNotFound);
12987 }
12988 
12989 
12990 MaybeObject* ObjectHashSet::Add(Object* key) {
12991  ASSERT(IsKey(key));
12992 
12993  // Make sure the key object has an identity hash code.
12994  int hash;
12995  { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
12996  if (maybe_hash->IsFailure()) return maybe_hash;
12997  hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
12998  }
12999  int entry = FindEntry(key);
13000 
13001  // Check whether key is already present.
13002  if (entry != kNotFound) return this;
13003 
13004  // Check whether the hash set should be extended and add entry.
13005  Object* obj;
13006  { MaybeObject* maybe_obj = EnsureCapacity(1, key);
13007  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
13008  }
13009  ObjectHashSet* table = ObjectHashSet::cast(obj);
13010  entry = table->FindInsertionEntry(hash);
13011  table->set(EntryToIndex(entry), key);
13012  table->ElementAdded();
13013  return table;
13014 }
13015 
13016 
13017 MaybeObject* ObjectHashSet::Remove(Object* key) {
13018  ASSERT(IsKey(key));
13019 
13020  // If the object does not have an identity hash, it was never used as a key.
13021  { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
13022  if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return this;
13023  }
13024  int entry = FindEntry(key);
13025 
13026  // Check whether key is actually present.
13027  if (entry == kNotFound) return this;
13028 
13029  // Remove entry and try to shrink this hash set.
13030  set_the_hole(EntryToIndex(entry));
13031  ElementRemoved();
13032  return Shrink(key);
13033 }
13034 
13035 
13036 Object* ObjectHashTable::Lookup(Object* key) {
13037  ASSERT(IsKey(key));
13038 
13039  // If the object does not have an identity hash, it was never used as a key.
13040  { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
13041  if (maybe_hash->ToObjectUnchecked()->IsUndefined()) {
13042  return GetHeap()->the_hole_value();
13043  }
13044  }
13045  int entry = FindEntry(key);
13046  if (entry == kNotFound) return GetHeap()->the_hole_value();
13047  return get(EntryToIndex(entry) + 1);
13048 }
13049 
13050 
13051 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) {
13052  ASSERT(IsKey(key));
13053 
13054  // Make sure the key object has an identity hash code.
13055  int hash;
13056  { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
13057  if (maybe_hash->IsFailure()) return maybe_hash;
13058  hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
13059  }
13060  int entry = FindEntry(key);
13061 
13062  // Check whether to perform removal operation.
13063  if (value->IsTheHole()) {
13064  if (entry == kNotFound) return this;
13065  RemoveEntry(entry);
13066  return Shrink(key);
13067  }
13068 
13069  // Key is already in table, just overwrite value.
13070  if (entry != kNotFound) {
13071  set(EntryToIndex(entry) + 1, value);
13072  return this;
13073  }
13074 
13075  // Check whether the hash table should be extended.
13076  Object* obj;
13077  { MaybeObject* maybe_obj = EnsureCapacity(1, key);
13078  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
13079  }
13080  ObjectHashTable* table = ObjectHashTable::cast(obj);
13081  table->AddEntry(table->FindInsertionEntry(hash), key, value);
13082  return table;
13083 }
13084 
13085 
13086 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
13087  set(EntryToIndex(entry), key);
13088  set(EntryToIndex(entry) + 1, value);
13089  ElementAdded();
13090 }
13091 
13092 
13093 void ObjectHashTable::RemoveEntry(int entry) {
13094  set_the_hole(EntryToIndex(entry));
13095  set_the_hole(EntryToIndex(entry) + 1);
13096  ElementRemoved();
13097 }
13098 
13099 
13100 #ifdef ENABLE_DEBUGGER_SUPPORT
13101 // Check if there is a break point at this code position.
13102 bool DebugInfo::HasBreakPoint(int code_position) {
13103  // Get the break point info object for this code position.
13104  Object* break_point_info = GetBreakPointInfo(code_position);
13105 
13106  // If there is no break point info object or no break points in the break
13107  // point info object there is no break point at this code position.
13108  if (break_point_info->IsUndefined()) return false;
13109  return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
13110 }
13111 
13112 
13113 // Get the break point info object for this code position.
13114 Object* DebugInfo::GetBreakPointInfo(int code_position) {
13115  // Find the index of the break point info object for this code position.
13116  int index = GetBreakPointInfoIndex(code_position);
13117 
13118  // Return the break point info object if any.
13119  if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
13120  return BreakPointInfo::cast(break_points()->get(index));
13121 }
13122 
13123 
13124 // Clear a break point at the specified code position.
13125 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
13126  int code_position,
13127  Handle<Object> break_point_object) {
13128  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
13129  if (break_point_info->IsUndefined()) return;
13130  BreakPointInfo::ClearBreakPoint(
13131  Handle<BreakPointInfo>::cast(break_point_info),
13132  break_point_object);
13133 }
13134 
13135 
13136 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
13137  int code_position,
13138  int source_position,
13139  int statement_position,
13140  Handle<Object> break_point_object) {
13141  Isolate* isolate = Isolate::Current();
13142  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
13143  if (!break_point_info->IsUndefined()) {
13144  BreakPointInfo::SetBreakPoint(
13145  Handle<BreakPointInfo>::cast(break_point_info),
13146  break_point_object);
13147  return;
13148  }
13149 
13150  // Adding a new break point for a code position which did not have any
13151  // break points before. Try to find a free slot.
13152  int index = kNoBreakPointInfo;
13153  for (int i = 0; i < debug_info->break_points()->length(); i++) {
13154  if (debug_info->break_points()->get(i)->IsUndefined()) {
13155  index = i;
13156  break;
13157  }
13158  }
13159  if (index == kNoBreakPointInfo) {
13160  // No free slot - extend break point info array.
13161  Handle<FixedArray> old_break_points =
13162  Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
13163  Handle<FixedArray> new_break_points =
13164  isolate->factory()->NewFixedArray(
13165  old_break_points->length() +
13166  Debug::kEstimatedNofBreakPointsInFunction);
13167 
13168  debug_info->set_break_points(*new_break_points);
13169  for (int i = 0; i < old_break_points->length(); i++) {
13170  new_break_points->set(i, old_break_points->get(i));
13171  }
13172  index = old_break_points->length();
13173  }
13174  ASSERT(index != kNoBreakPointInfo);
13175 
13176  // Allocate new BreakPointInfo object and set the break point.
13177  Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
13178  isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
13179  new_break_point_info->set_code_position(Smi::FromInt(code_position));
13180  new_break_point_info->set_source_position(Smi::FromInt(source_position));
13181  new_break_point_info->
13182  set_statement_position(Smi::FromInt(statement_position));
13183  new_break_point_info->set_break_point_objects(
13184  isolate->heap()->undefined_value());
13185  BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
13186  debug_info->break_points()->set(index, *new_break_point_info);
13187 }
13188 
13189 
13190 // Get the break point objects for a code position.
13191 Object* DebugInfo::GetBreakPointObjects(int code_position) {
13192  Object* break_point_info = GetBreakPointInfo(code_position);
13193  if (break_point_info->IsUndefined()) {
13194  return GetHeap()->undefined_value();
13195  }
13196  return BreakPointInfo::cast(break_point_info)->break_point_objects();
13197 }
13198 
13199 
13200 // Get the total number of break points.
13201 int DebugInfo::GetBreakPointCount() {
13202  if (break_points()->IsUndefined()) return 0;
13203  int count = 0;
13204  for (int i = 0; i < break_points()->length(); i++) {
13205  if (!break_points()->get(i)->IsUndefined()) {
13206  BreakPointInfo* break_point_info =
13207  BreakPointInfo::cast(break_points()->get(i));
13208  count += break_point_info->GetBreakPointCount();
13209  }
13210  }
13211  return count;
13212 }
13213 
13214 
13215 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
13216  Handle<Object> break_point_object) {
13217  Heap* heap = debug_info->GetHeap();
13218  if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
13219  for (int i = 0; i < debug_info->break_points()->length(); i++) {
13220  if (!debug_info->break_points()->get(i)->IsUndefined()) {
13221  Handle<BreakPointInfo> break_point_info =
13222  Handle<BreakPointInfo>(BreakPointInfo::cast(
13223  debug_info->break_points()->get(i)));
13224  if (BreakPointInfo::HasBreakPointObject(break_point_info,
13225  break_point_object)) {
13226  return *break_point_info;
13227  }
13228  }
13229  }
13230  return heap->undefined_value();
13231 }
13232 
13233 
13234 // Find the index of the break point info object for the specified code
13235 // position.
13236 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
13237  if (break_points()->IsUndefined()) return kNoBreakPointInfo;
13238  for (int i = 0; i < break_points()->length(); i++) {
13239  if (!break_points()->get(i)->IsUndefined()) {
13240  BreakPointInfo* break_point_info =
13241  BreakPointInfo::cast(break_points()->get(i));
13242  if (break_point_info->code_position()->value() == code_position) {
13243  return i;
13244  }
13245  }
13246  }
13247  return kNoBreakPointInfo;
13248 }
13249 
13250 
13251 // Remove the specified break point object.
13252 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
13253  Handle<Object> break_point_object) {
13254  Isolate* isolate = Isolate::Current();
13255  // If there are no break points just ignore.
13256  if (break_point_info->break_point_objects()->IsUndefined()) return;
13257  // If there is a single break point clear it if it is the same.
13258  if (!break_point_info->break_point_objects()->IsFixedArray()) {
13259  if (break_point_info->break_point_objects() == *break_point_object) {
13260  break_point_info->set_break_point_objects(
13261  isolate->heap()->undefined_value());
13262  }
13263  return;
13264  }
13265  // If there are multiple break points shrink the array
13266  ASSERT(break_point_info->break_point_objects()->IsFixedArray());
13267  Handle<FixedArray> old_array =
13268  Handle<FixedArray>(
13269  FixedArray::cast(break_point_info->break_point_objects()));
13270  Handle<FixedArray> new_array =
13271  isolate->factory()->NewFixedArray(old_array->length() - 1);
13272  int found_count = 0;
13273  for (int i = 0; i < old_array->length(); i++) {
13274  if (old_array->get(i) == *break_point_object) {
13275  ASSERT(found_count == 0);
13276  found_count++;
13277  } else {
13278  new_array->set(i - found_count, old_array->get(i));
13279  }
13280  }
13281  // If the break point was found in the list change it.
13282  if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
13283 }
13284 
13285 
13286 // Add the specified break point object.
13287 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
13288  Handle<Object> break_point_object) {
13289  // If there was no break point objects before just set it.
13290  if (break_point_info->break_point_objects()->IsUndefined()) {
13291  break_point_info->set_break_point_objects(*break_point_object);
13292  return;
13293  }
13294  // If the break point object is the same as before just ignore.
13295  if (break_point_info->break_point_objects() == *break_point_object) return;
13296  // If there was one break point object before replace with array.
13297  if (!break_point_info->break_point_objects()->IsFixedArray()) {
13298  Handle<FixedArray> array = FACTORY->NewFixedArray(2);
13299  array->set(0, break_point_info->break_point_objects());
13300  array->set(1, *break_point_object);
13301  break_point_info->set_break_point_objects(*array);
13302  return;
13303  }
13304  // If there was more than one break point before extend array.
13305  Handle<FixedArray> old_array =
13306  Handle<FixedArray>(
13307  FixedArray::cast(break_point_info->break_point_objects()));
13308  Handle<FixedArray> new_array =
13309  FACTORY->NewFixedArray(old_array->length() + 1);
13310  for (int i = 0; i < old_array->length(); i++) {
13311  // If the break point was there before just ignore.
13312  if (old_array->get(i) == *break_point_object) return;
13313  new_array->set(i, old_array->get(i));
13314  }
13315  // Add the new break point.
13316  new_array->set(old_array->length(), *break_point_object);
13317  break_point_info->set_break_point_objects(*new_array);
13318 }
13319 
13320 
13321 bool BreakPointInfo::HasBreakPointObject(
13322  Handle<BreakPointInfo> break_point_info,
13323  Handle<Object> break_point_object) {
13324  // No break point.
13325  if (break_point_info->break_point_objects()->IsUndefined()) return false;
13326  // Single break point.
13327  if (!break_point_info->break_point_objects()->IsFixedArray()) {
13328  return break_point_info->break_point_objects() == *break_point_object;
13329  }
13330  // Multiple break points.
13331  FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
13332  for (int i = 0; i < array->length(); i++) {
13333  if (array->get(i) == *break_point_object) {
13334  return true;
13335  }
13336  }
13337  return false;
13338 }
13339 
13340 
13341 // Get the number of break points.
13342 int BreakPointInfo::GetBreakPointCount() {
13343  // No break point.
13344  if (break_point_objects()->IsUndefined()) return 0;
13345  // Single break point.
13346  if (!break_point_objects()->IsFixedArray()) return 1;
13347  // Multiple break points.
13348  return FixedArray::cast(break_point_objects())->length();
13349 }
13350 #endif // ENABLE_DEBUGGER_SUPPORT
13351 
13352 
13353 Object* JSDate::GetField(Object* object, Smi* index) {
13354  return JSDate::cast(object)->DoGetField(
13355  static_cast<FieldIndex>(index->value()));
13356 }
13357 
13358 
13359 Object* JSDate::DoGetField(FieldIndex index) {
13360  ASSERT(index != kDateValue);
13361 
13362  DateCache* date_cache = GetIsolate()->date_cache();
13363 
13364  if (index < kFirstUncachedField) {
13365  Object* stamp = cache_stamp();
13366  if (stamp != date_cache->stamp() && stamp->IsSmi()) {
13367  // Since the stamp is not NaN, the value is also not NaN.
13368  int64_t local_time_ms =
13369  date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
13370  SetLocalFields(local_time_ms, date_cache);
13371  }
13372  switch (index) {
13373  case kYear: return year();
13374  case kMonth: return month();
13375  case kDay: return day();
13376  case kWeekday: return weekday();
13377  case kHour: return hour();
13378  case kMinute: return min();
13379  case kSecond: return sec();
13380  default: UNREACHABLE();
13381  }
13382  }
13383 
13384  if (index >= kFirstUTCField) {
13385  return GetUTCField(index, value()->Number(), date_cache);
13386  }
13387 
13388  double time = value()->Number();
13389  if (isnan(time)) return GetIsolate()->heap()->nan_value();
13390 
13391  int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
13392  int days = DateCache::DaysFromTime(local_time_ms);
13393 
13394  if (index == kDays) return Smi::FromInt(days);
13395 
13396  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
13397  if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
13398  ASSERT(index == kTimeInDay);
13399  return Smi::FromInt(time_in_day_ms);
13400 }
13401 
13402 
13403 Object* JSDate::GetUTCField(FieldIndex index,
13404  double value,
13405  DateCache* date_cache) {
13406  ASSERT(index >= kFirstUTCField);
13407 
13408  if (isnan(value)) return GetIsolate()->heap()->nan_value();
13409 
13410  int64_t time_ms = static_cast<int64_t>(value);
13411 
13412  if (index == kTimezoneOffset) {
13413  return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
13414  }
13415 
13416  int days = DateCache::DaysFromTime(time_ms);
13417 
13418  if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
13419 
13420  if (index <= kDayUTC) {
13421  int year, month, day;
13422  date_cache->YearMonthDayFromDays(days, &year, &month, &day);
13423  if (index == kYearUTC) return Smi::FromInt(year);
13424  if (index == kMonthUTC) return Smi::FromInt(month);
13425  ASSERT(index == kDayUTC);
13426  return Smi::FromInt(day);
13427  }
13428 
13429  int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
13430  switch (index) {
13431  case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
13432  case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
13433  case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
13434  case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
13435  case kDaysUTC: return Smi::FromInt(days);
13436  case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
13437  default: UNREACHABLE();
13438  }
13439 
13440  UNREACHABLE();
13441  return NULL;
13442 }
13443 
13444 
13445 void JSDate::SetValue(Object* value, bool is_value_nan) {
13446  set_value(value);
13447  if (is_value_nan) {
13448  HeapNumber* nan = GetIsolate()->heap()->nan_value();
13449  set_cache_stamp(nan, SKIP_WRITE_BARRIER);
13450  set_year(nan, SKIP_WRITE_BARRIER);
13451  set_month(nan, SKIP_WRITE_BARRIER);
13452  set_day(nan, SKIP_WRITE_BARRIER);
13453  set_hour(nan, SKIP_WRITE_BARRIER);
13454  set_min(nan, SKIP_WRITE_BARRIER);
13455  set_sec(nan, SKIP_WRITE_BARRIER);
13456  set_weekday(nan, SKIP_WRITE_BARRIER);
13457  } else {
13459  }
13460 }
13461 
13462 
13463 void JSDate::SetLocalFields(int64_t local_time_ms, DateCache* date_cache) {
13464  int days = DateCache::DaysFromTime(local_time_ms);
13465  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
13466  int year, month, day;
13467  date_cache->YearMonthDayFromDays(days, &year, &month, &day);
13468  int weekday = date_cache->Weekday(days);
13469  int hour = time_in_day_ms / (60 * 60 * 1000);
13470  int min = (time_in_day_ms / (60 * 1000)) % 60;
13471  int sec = (time_in_day_ms / 1000) % 60;
13472  set_cache_stamp(date_cache->stamp());
13473  set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13474  set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13475  set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13476  set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13477  set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13478  set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13479  set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13480 }
13481 
13482 } } // namespace v8::internal
static bool IsBlack(MarkBit mark_bit)
Definition: mark-compact.h:70
Object * GetPrototype()
Definition: objects.cc:725
MUST_USE_RESULT MaybeObject * CopyInsertDescriptor(Descriptor *descriptor, TransitionFlag flag)
Definition: objects.cc:5186
byte * Address
Definition: globals.h:157
MUST_USE_RESULT MaybeObject * GetElementWithReceiver(Object *receiver, uint32_t index)
Definition: objects.cc:667
bool FLAG_enable_slow_asserts
MUST_USE_RESULT MaybeObject * GetElementWithInterceptor(Object *receiver, uint32_t index)
Definition: objects.cc:10179
void SetEnumCache(FixedArray *bridge_storage, FixedArray *new_cache, Object *new_index_cache)
Definition: objects.cc:6053
MUST_USE_RESULT MaybeObject * LookupAsciiSymbol(Vector< const char > str, Object **s)
Definition: objects.cc:12163
void ClearTypeFeedbackCells(Heap *heap)
Definition: objects.cc:8429
Object * Lookup(MapHandleList *maps, int code_kind)
Definition: objects.cc:5923
int IndexInCodeCache(Object *name, Code *code)
Definition: objects.cc:5297
bool IsMatch(Object *string)
Definition: objects.cc:11175
void MarkForParallelRecompilation()
Definition: objects.cc:7543
static const int kRequiresSlowElementsTagSize
Definition: objects.h:3276
void set_elements_kind(ElementsKind elements_kind)
Definition: objects.h:4773
bool IsIdentifierPart(unibrow::uchar c)
Definition: scanner.h:155
void SetBackPointer(Object *value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
Definition: objects-inl.h:3775
StringKey(String *string)
Definition: objects.cc:10931
static Handle< Object > DeleteElement(Handle< JSObject > obj, uint32_t index)
Definition: objects.cc:3875
Object * KeyAt(int entry)
Definition: objects.h:2841
static uchar TrailSurrogate(int char_code)
Definition: unicode.h:146
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< String > key, Handle< Object > value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: objects.cc:1893
Code * builtin(Name name)
Definition: builtins.h:320
PropertyAttributes GetPropertyAttribute(String *name)
Definition: objects-inl.h:5063
static const int kGenerousAllocationCount
Definition: objects.h:5484
JSGlobalPropertyCell * Cell(int index)
Definition: objects-inl.h:5334
Object * get(AccessorComponent component)
Definition: objects.h:8441
#define SLOW_ASSERT(condition)
Definition: checks.h:276
static bool CompileLazy(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: objects.cc:7643
static DeoptimizationOutputData * cast(Object *obj)
uint32_t HashForObject(Object *other)
Definition: objects.cc:10946
void CopyValuesTo(FixedArray *elements)
Definition: objects.cc:10415
virtual void Seek(unsigned pos)
Definition: objects.cc:6676
MUST_USE_RESULT MaybeObject * SetIdentityHash(Smi *hash, CreationFlag flag)
Definition: objects.cc:3523
DateCache * date_cache()
Definition: isolate.h:1050
Object * Lookup(String *name, Code::Flags flags)
Definition: objects.cc:5603
#define CHECK_EQ(expected, value)
Definition: checks.h:219
static uchar LeadSurrogate(int char_code)
Definition: unicode.h:143
bool IsExternalArrayElementsKind(ElementsKind kind)
Definition: elements-kind.h:94
bool IsHoleyElementsKind(ElementsKind kind)
static const int kCodeEntryOffset
Definition: objects.h:6182
Object * LookupAccessor(String *name, AccessorComponent component)
Definition: objects.cc:4813
MUST_USE_RESULT MaybeObject * AllocateFixedArray(int length, PretenureFlag pretenure)
Definition: heap.cc:4819
static const int kArrayIndexHashMask
Definition: objects.h:7364
bool HasElementsTransition()
Definition: objects-inl.h:3670
void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset, unsigned chars)
Definition: objects.cc:6507
void InvalidateRelocation()
Definition: objects.cc:8278
uint32_t HashForObject(Object *obj)
Definition: objects.cc:11070
void AddCharacter(uint32_t c)
Definition: objects-inl.h:4964
const char * ToCString(const v8::String::Utf8Value &value)
void set_has_deoptimization_support(bool value)
Definition: objects-inl.h:3254
virtual uint32_t Hash()=0
Object * LookupRegExp(String *source, JSRegExp::Flags flags)
Definition: objects.cc:12257
Handle< String > SymbolFromString(Handle< String > value)
Definition: factory.cc:898
Handle< Value >(* NamedPropertySetter)(Local< String > property, Local< Value > value, const AccessorInfo &info)
Definition: v8.h:2061
uint32_t HashForObject(Object *obj)
Definition: objects.cc:12372
MUST_USE_RESULT MaybeObject * CopyDropDescriptors()
Definition: objects.cc:4938
#define RETURN_IF_SCHEDULED_EXCEPTION(isolate)
Definition: isolate.h:112
bool is_hidden_prototype()
Definition: objects.h:4725
void set(int index, Object *value)
Definition: objects-inl.h:1757
MUST_USE_RESULT MaybeObject * TransformPropertiesToFastFor(JSObject *obj, int unused_property_fields)
Definition: objects.cc:12836
int SearchOptimizedCodeMap(Context *native_context)
Definition: objects.cc:8194
void AddSurrogatePair(uc32 c)
Definition: objects.cc:7308
void PrintF(const char *format,...)
Definition: v8utils.cc:40
static void DoGenerateNewEnumerationIndices(Handle< StringDictionary > dictionary)
Definition: objects.cc:12427
MUST_USE_RESULT MaybeObject * GetPropertyWithCallback(Object *receiver, Object *structure, String *name)
Definition: objects.cc:165
virtual MUST_USE_RESULT MaybeObject * Delete(JSObject *holder, uint32_t key, JSReceiver::DeleteMode mode)=0
bool InNewSpace(Object *object)
Definition: heap-inl.h:288
unsigned stack_slots()
Definition: objects-inl.h:3318
bool EquivalentToForNormalization(Map *other, PropertyNormalizationMode mode)
Definition: objects.cc:7511
static TypeFeedbackInfo * cast(Object *obj)
static String * cast(Object *obj)
MUST_USE_RESULT MaybeObject * Add(Key key, Object *value, PropertyDetails details)
Definition: objects.cc:12556
StringSharedKey(String *source, SharedFunctionInfo *shared, LanguageMode language_mode, int scope_position)
Definition: objects.cc:10958
void SetValue(Object *value, bool is_value_nan)
Definition: objects.cc:13445
void DetailsAtPut(int entry, PropertyDetails value)
Definition: objects.h:3084
MUST_USE_RESULT MaybeObject * SetPropertyWithDefinedSetter(JSReceiver *setter, Object *value)
Definition: objects.cc:1998
MUST_USE_RESULT MaybeObject * AllocateSubString(String *buffer, int start, int end, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:3344
void SetThisPropertyAssignmentsInfo(bool has_only_simple_this_property_assignments, FixedArray *this_property_assignments)
Definition: objects.cc:7905
MaybeObject * TryFlatten(PretenureFlag pretenure=NOT_TENURED)
Definition: objects-inl.h:2428
MUST_USE_RESULT PropertyAttributes GetElementAttributeWithHandler(JSReceiver *receiver, uint32_t index)
Definition: objects.cc:2735
MUST_USE_RESULT MaybeObject * PrepareSlowElementsForSort(uint32_t limit)
Definition: objects.cc:11612
const uint32_t kTwoByteStringTag
Definition: objects.h:469
uint32_t NumberToUint32(Object *number)
Definition: v8conversions.h:43
bool HasRealElementProperty(uint32_t index)
Definition: objects.cc:10540
bool function_with_prototype()
Definition: objects-inl.h:3068
void set_opt_count(int opt_count)
Handle< DescriptorArray > NewDescriptorArray(int number_of_descriptors, int slack=0)
Definition: factory.cc:115
unsigned Utf16Length()
Definition: unicode.cc:342
uint32_t HashForObject(Object *other)
Definition: objects.cc:11281
static Failure * InternalError()
Definition: objects-inl.h:1019
void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6346
int NumberOfLocalElements(PropertyAttributes filter)
Definition: objects.cc:10767
Object * ToBoolean(bool condition)
Definition: heap-inl.h:652
void DeleteHiddenProperty(String *key)
Definition: objects.cc:3651
Isolate * isolate()
Definition: heap-inl.h:503
int unused_property_fields()
Definition: objects-inl.h:3019
void set_length(Smi *length)
Definition: objects-inl.h:5278
void SourceCodePrint(StringStream *accumulator, int max_length)
Definition: objects.cc:7963
PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject *receiver, String *name, bool continue_search)
Definition: objects.cc:3077
MUST_USE_RESULT MaybeObject * Put(MapHandleList *maps, int code_kind, Code *code)
Definition: objects.cc:5932
MUST_USE_RESULT MaybeObject * ConvertTransitionToMapTransition(int transition_index, String *name, Object *new_value, PropertyAttributes attributes)
Definition: objects.cc:1758
static const char * Name(Value tok)
Definition: token.h:196
static Smi * FromInt(int value)
Definition: objects-inl.h:981
bool IsFastObjectElementsKind(ElementsKind kind)
bool allowed_in_shared_map_code_cache()
Definition: objects.cc:8442
void IteratePointer(ObjectVisitor *v, int offset)
Definition: objects-inl.h:1193
NormalizedMapSharingMode
Definition: objects.h:161
#define LOG(isolate, Call)
Definition: log.h:81
RegExpKey(String *string, JSRegExp::Flags flags)
Definition: objects.cc:11047
unsigned stack_check_table_offset()
Definition: objects-inl.h:3351
Map * elements_transition_map()
Definition: objects-inl.h:3681
void LookupTransition(JSObject *holder, String *name, LookupResult *result)
Definition: objects-inl.h:2071
void CopyKeysTo(FixedArray *storage, PropertyAttributes filter, SortMode sort_mode)
static Object * GetObjectFromEntryAddress(Address location_of_address)
Definition: objects-inl.h:3570
void ReportFailedAccessCheck(JSObject *receiver, v8::AccessType type)
Definition: isolate.cc:773
MUST_USE_RESULT MaybeObject * GetElementWithHandler(Object *receiver, uint32_t index)
Definition: objects.cc:258
uint64_t double_to_uint64(double d)
Definition: double.h:37
void AddSurrogatePairNoIndex(uc32 c)
Definition: objects.cc:7316
MaybeObject * AsObject()
Definition: objects.cc:11109
bool IsMatch(Object *string)
Definition: objects.cc:11275
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset kInstanceClassNameOffset kHiddenPrototypeBit kReadOnlyPrototypeBit kIsTopLevelBit allows_lazy_compilation
Definition: objects-inl.h:3939
bool HasRealNamedProperty(String *key)
Definition: objects.cc:10524
int NumberOfOwnDescriptors()
Definition: objects.h:4944
SequentialSymbolKey(Vector< const Char > string, uint32_t seed)
Definition: objects.cc:11125
MUST_USE_RESULT MaybeObject * Update(String *name, Code *code)
Definition: objects.cc:5509
void CopyTo(int pos, FixedArray *dest, int dest_pos, int len)
Definition: objects.cc:6012
MUST_USE_RESULT MaybeObject * GetPropertyWithDefinedGetter(Object *receiver, JSReceiver *getter)
Definition: objects.cc:286
MUST_USE_RESULT MaybeObject * SetPropertyWithFailedAccessCheck(LookupResult *result, String *name, Object *value, bool check_prototype, StrictModeFlag strict_mode)
Definition: objects.cc:2450
void VerifyApiCallResultType()
Definition: objects-inl.h:1715
static HeapObject * cast(Object *obj)
MUST_USE_RESULT MaybeObject * Rehash(HashTable *new_table, Key key)
Definition: objects.cc:11391
MUST_USE_RESULT MaybeObject * SetInstancePrototype(Object *value)
Definition: objects.cc:7702
static Handle< T > cast(Handle< S > that)
Definition: handles.h:81
MUST_USE_RESULT MaybeObject * SetPrototype(Object *value)
Definition: objects.cc:7735
static bool EncodeNonAsciiCharacter(uchar c, byte *buffer, unsigned capacity, unsigned &offset)
Definition: unicode-inl.h:170
bool MayNamedAccess(JSObject *receiver, Object *key, v8::AccessType type)
Definition: isolate.cc:828
static const int kMaxHashCalcLength
Definition: objects.h:7390
MUST_USE_RESULT MaybeObject * AllocateCodeCache()
Definition: heap.cc:2117
void set_pre_allocated_property_fields(int value)
Definition: objects-inl.h:3001
const unibrow::byte * ExternalAsciiStringReadBlock(unsigned *remaining, unsigned *offset, unsigned chars)
Definition: objects.cc:6463
static CodeCacheHashTable * cast(Object *obj)
static const int kProtoTransitionElementsPerEntry
Definition: objects.h:4904
static AccessorPair * cast(Object *obj)
MUST_USE_RESULT MaybeObject * AddKeysFromJSArray(JSArray *array)
Definition: objects.cc:5953
static void IterateBody(HeapObject *obj, int object_size, ObjectVisitor *v)
static Failure * OutOfMemoryException()
Definition: objects-inl.h:1029
JSFunction * GetConstantFunction(int descriptor_number)
Definition: objects-inl.h:2146
void ZapPrototypeTransitions()
Definition: objects.cc:9006
PropertyAttributes property_attributes()
Definition: objects-inl.h:5125
bool IsAsciiRepresentation()
Definition: objects-inl.h:290
TwoCharHashTableKey(uint32_t c1, uint32_t c2, uint32_t seed)
Definition: objects.cc:12069
HeapObject * UncheckedPrototypeTransitions()
static ExternalTwoByteString * cast(Object *obj)
bool IsMatch(Object *obj)
Definition: objects.cc:11055
void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6476
TraversableMap * GetAndResetParent()
Definition: objects.cc:5440
int GetEnumElementKeys(FixedArray *storage)
Definition: objects.cc:10922
void ZapTransitions()
Definition: objects.cc:8998
int32_t uc32
Definition: globals.h:260
MUST_USE_RESULT MaybeObject * GetPropertyWithFailedAccessCheck(Object *receiver, LookupResult *result, String *name, PropertyAttributes *attributes)
Definition: objects.cc:311
SeededNumberDictionary * element_dictionary()
Definition: objects-inl.h:4905
static uint32_t StringHash(Object *obj)
Definition: objects.cc:11304
Vector< const char > ToAsciiVector()
Definition: objects.h:7139
static Map * cast(Object *obj)
MUST_USE_RESULT MaybeObject * AddNumberEntry(uint32_t key, Object *value, PropertyDetails details)
Definition: objects.cc:12624
MUST_USE_RESULT MaybeObject * Put(String *src, Context *context, Object *value)
Definition: objects.cc:12266
Object * ToBoolean()
Definition: objects.cc:107
static StubType ExtractTypeFromFlags(Flags flags)
Definition: objects-inl.h:3538
MUST_USE_RESULT MaybeObject * ConvertDescriptorToField(String *name, Object *new_value, PropertyAttributes attributes)
Definition: objects.cc:1808
MUST_USE_RESULT MaybeObject * GetPropertyWithReceiver(Object *receiver, String *key, PropertyAttributes *attributes)
Definition: objects.cc:154
static ByteArray * cast(Object *obj)
static uint32_t ComputeHashField(unibrow::CharacterStream *buffer, int length, uint32_t seed)
Definition: objects.cc:7336
T & at(int i) const
Definition: list.h:90
MUST_USE_RESULT MaybeObject * SetElementWithCallbackSetterInPrototypes(uint32_t index, Object *value, bool *found, StrictModeFlag strict_mode)
Definition: objects.cc:2022
MUST_USE_RESULT MaybeObject * AsObject()
Definition: objects.cc:5715
Builtins * builtins()
Definition: isolate.h:924
void ConsStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6777
static FreeSpace * cast(Object *obj)
virtual MUST_USE_RESULT MaybeObject * CopyElements(JSObject *source_holder, uint32_t source_start, FixedArrayBase *destination, ElementsKind destination_kind, uint32_t destination_start, int copy_size, FixedArrayBase *source=NULL)=0
void ClearInstanceofCache()
Definition: heap-inl.h:647
void Set(int descriptor_number, Descriptor *desc, const WhitenessWitness &)
Definition: objects-inl.h:2171
bool VerifyBailoutId(BailoutId id)
Definition: objects.cc:8056
MUST_USE_RESULT MaybeObject * Uint32ToString(uint32_t value, bool check_number_string_cache=true)
Definition: heap.cc:3039
bool SameValue(Object *other)
Definition: objects.cc:780
void Relocate(intptr_t delta)
Definition: objects.cc:8283
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset kInstanceClassNameOffset kHiddenPrototypeBit kReadOnlyPrototypeBit is_toplevel
Definition: objects-inl.h:3932
static Failure * Exception()
Definition: objects-inl.h:1024
MUST_USE_RESULT MaybeObject * PutRegExp(String *src, JSRegExp::Flags flags, FixedArray *value)
Definition: objects.cc:12319
MUST_USE_RESULT MaybeObject * CopyReplaceDescriptors(DescriptorArray *descriptors, String *name, TransitionFlag flag, int descriptor_index)
Definition: objects.cc:5029
#define REGISTER(N, C)
const int kMaxInt
Definition: globals.h:210
void SetKey(int transition_number, String *value)
static Foreign * cast(Object *obj)
static bool enabled()
Definition: serialize.h:481
MUST_USE_RESULT MaybeObject * GetElementsTransitionMapSlow(ElementsKind elements_kind)
Definition: objects.cc:2338
MUST_USE_RESULT MaybeObject * ToObject()
Definition: objects.cc:85
MUST_USE_RESULT MaybeObject * PrepareElementsForSort(uint32_t limit)
Definition: objects.cc:11711
void set_map(Map *value)
Definition: objects-inl.h:1143
Map * SymbolMapForString(String *str)
Definition: heap.cc:4490
bool MakeExternal(v8::String::ExternalStringResource *resource)
Definition: objects.cc:924
int GetLocalElementKeys(FixedArray *storage, PropertyAttributes filter)
Definition: objects.cc:10786
struct v8::internal::IeeeDoubleBigEndianArchType::@33 bits
int SourceStatementPosition(Address pc)
Definition: objects.cc:8368
Map * LookupElementsTransitionMap(ElementsKind elements_kind)
Definition: objects.cc:2290
void PrintElementsTransition(FILE *file, ElementsKind from_kind, FixedArrayBase *from_elements, ElementsKind to_kind, FixedArrayBase *to_elements)
Definition: objects.cc:1167
static const int kSize
Definition: objects.h:7748
static AliasedArgumentsEntry * cast(Object *obj)
bool IsTwoByteEqualTo(Vector< const uc16 > str)
Definition: objects.cc:7199
uint16_t SlicedStringGet(int index)
Definition: objects.cc:6865
bool Contains(Object *key)
Definition: objects.cc:12979
static Handle< Object > TransitionElementsKind(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:10072
void SetEnumLength(int length)
Definition: objects.h:4959
Handle< Object > Lookup(MapHandleList *maps, Code::Flags flags)
Definition: objects.cc:5819
Object * HeapNumberToBoolean()
Definition: objects.cc:1434
static bool CompileOptimized(Handle< JSFunction > function, BailoutId osr_ast_id, ClearExceptionFlag flag)
Definition: objects.cc:7659
List< Handle< Map > > MapHandleList
Definition: list.h:198
#define ASSERT(condition)
Definition: checks.h:270
bool CanTransitionToMoreGeneralFastElementsKind(ElementsKind elements_kind, bool allow_only_packed)
v8::Handle< v8::Value > Print(const v8::Arguments &args)
static void IncrementLiveBytesFromGC(Address address, int by)
Definition: spaces.h:484
MUST_USE_RESULT MaybeObject * SetElement(uint32_t index, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode, bool check_prototype)
Definition: objects.cc:9859
static Handle< Object > SetOwnElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictModeFlag strict_mode)
Definition: objects.cc:9874
MUST_USE_RESULT MaybeObject * PreventExtensions()
Definition: objects.cc:4143
Map * GetPrototypeTransition(Object *prototype)
Definition: objects.cc:8938
static void AppendCallbackDescriptors(Handle< Map > map, Handle< Object > descriptors)
Definition: objects.cc:2187
static ExternalUnsignedShortArray * cast(Object *obj)
MUST_USE_RESULT MaybeObject * UnionOfKeys(FixedArray *other)
Definition: objects.cc:5971
static Script * cast(Object *obj)
MUST_USE_RESULT MaybeObject * PutEval(String *src, Context *context, SharedFunctionInfo *value, int scope_position)
Definition: objects.cc:12290
unsigned short uint16_t
Definition: unicode.cc:46
int SourcePosition(Address pc)
Definition: objects.cc:8336
MUST_USE_RESULT MaybeObject * EnsureCapacity(int n, Key key)
Definition: objects.cc:11425
#define VISITOR_SYNCHRONIZATION_TAGS_LIST(V)
Definition: objects.h:8837
static Dictionary< Shape, Key > * cast(Object *obj)
Definition: objects.h:3062
#define CALL_HEAP_FUNCTION_VOID(ISOLATE, FUNCTION_CALL)
Definition: heap-inl.h:565
MUST_USE_RESULT MaybeObject * EnsureCapacity(int n, Key key)
Definition: objects.cc:12493
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11937
void clear_pending_exception()
Definition: isolate.h:555
static Context * cast(Object *context)
Definition: contexts.h:212
static MUST_USE_RESULT MaybeObject * Allocate(int deopt_entry_count, PretenureFlag pretenure)
Definition: objects.cc:6156
Object * SlowReverseLookup(Object *value)
Definition: objects.cc:4867
MUST_USE_RESULT MaybeObject * LookupSymbol(Vector< const char > str)
Definition: heap.cc:5434
static const int kSourceIndex
Definition: objects.h:6629
PropertyAttributes GetPropertyAttributePostInterceptor(JSObject *receiver, String *name, bool continue_search)
Definition: objects.cc:3056
static SharedFunctionInfo * cast(Object *obj)
const uint32_t kStringRepresentationMask
Definition: objects.h:474
int SizeFromMap(Map *map)
Definition: objects-inl.h:2954
void set(int index, float value)
Definition: objects-inl.h:2902
#define CHECK(condition)
Definition: checks.h:56
bool HasElementWithInterceptor(JSReceiver *receiver, uint32_t index)
Definition: objects.cc:9111
void RemoveFromCodeCache(String *name, Code *code, int index)
Definition: objects.cc:5306
static const int kShortSize
Definition: objects.h:7746
Handle< Value >(* IndexedPropertySetter)(uint32_t index, Local< Value > value, const AccessorInfo &info)
Definition: v8.h:2101
bool IsOptimizing() const
Definition: compiler.h:150
MaybeObject * AsObject()
Definition: objects.cc:11179
int isnan(double x)
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:282
SmartArrayPointer< uc16 > ToWideCString(RobustnessFlag robustness_flag=FAST_STRING_TRAVERSAL)
Definition: objects.cc:6318
Handle< String > NumberToString(Handle< Object > number)
Definition: factory.cc:1076
MUST_USE_RESULT MaybeObject * Copy()
Definition: objects.cc:5130
bool ReferencesObject(Object *obj)
Definition: objects.cc:4030
void ReplaceCode(Code *code)
Definition: objects-inl.h:4362
const uc16 * GetTwoByteData()
Definition: objects.cc:6292
void set_map_and_elements(Map *map, FixedArrayBase *value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
Definition: objects-inl.h:1360
Factory * factory()
Definition: isolate.h:992
bool IsFastElementsKind(ElementsKind kind)
static ExternalAsciiString * cast(Object *obj)
MUST_USE_RESULT MaybeObject * EnsureWritableFastElements()
Definition: objects-inl.h:4881
PropertyAttributes
void set_the_hole(int index)
Definition: objects-inl.h:1900
static const int kInvalidStamp
Definition: date.h:63
MUST_USE_RESULT MaybeObject * GetPropertyWithInterceptor(Object *receiver, String *name, PropertyAttributes *attributes)
Definition: objects.cc:10482
MUST_USE_RESULT MaybeObject * DeletePropertyWithHandler(String *name, DeleteMode mode)
Definition: objects.cc:2646
static Code * cast(Object *obj)
Handle< String > LookupAsciiSymbol(Vector< const char > str)
Definition: factory.cc:174
bool IsMatch(Object *string)
Definition: objects.cc:10935
virtual const uint16_t * data() const =0
static Handle< Object > SetHiddenProperty(Handle< JSObject > obj, Handle< String > key, Handle< Object > value)
Definition: objects.cc:3601
MUST_USE_RESULT MaybeObject * AllocateInternalSymbol(unibrow::CharacterStream *buffer, int chars, uint32_t hash_field)
Definition: heap.cc:4514
static uint32_t StringSharedHashHelper(String *source, SharedFunctionInfo *shared, LanguageMode language_mode, int scope_position)
Definition: objects.cc:10984
void set(int index, uint32_t value)
Definition: objects-inl.h:2883
MUST_USE_RESULT MaybeObject * LookupSubStringAsciiSymbol(Handle< SeqAsciiString > str, int from, int length, Object **s)
Definition: objects.cc:12170
bool HasElementWithReceiver(JSReceiver *receiver, uint32_t index)
Definition: objects.cc:9277
int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind)
bool AsArrayIndex(uint32_t *index)
Definition: objects-inl.h:5028
Object * GetValue(int descriptor_number)
Definition: objects-inl.h:2123
static Object ** RawField(HeapObject *obj, int offset)
Definition: objects-inl.h:971
const int kIntSize
Definition: globals.h:217
Object * GetNormalizedProperty(LookupResult *result)
Definition: objects.cc:434
MUST_USE_RESULT MaybeObject * AllocateHeapNumber(double value, PretenureFlag pretenure)
Definition: heap.cc:2483
static Smi * cast(Object *object)
static const char * AllocationIndexToString(int index)
static void IterateBody(HeapObject *obj, ObjectVisitor *v)
Definition: objects-inl.h:5503
unsigned int seed
Definition: test-strings.cc:18
void PrintOn(FILE *out)
Definition: objects.cc:7371
static const int kInvalidEnumCache
Definition: objects.h:5121
void ClearCodeCache(Heap *heap)
Definition: objects-inl.h:5250
static const int kZeroHash
Definition: objects.h:7017
bool Equals(String *other)
Definition: objects-inl.h:2419
Handle< String > SubString(Handle< String > str, int start, int end, PretenureFlag pretenure)
Definition: handles.cc:326
MUST_USE_RESULT MaybeObject * Get(JSObject *object, PropertyNormalizationMode mode)
Definition: objects.cc:3193
void Lookup(String *name, LookupResult *result)
Definition: objects.cc:132
Vector< const char > string_
Definition: objects.cc:11115
MaybeObject *(* setter)(JSObject *object, Object *value, void *data)
Definition: v8globals.h:343
Handle< Object > CallTrap(const char *name, Handle< Object > derived_trap, int argc, Handle< Object > args[])
Definition: objects.cc:2770
static ExternalShortArray * cast(Object *obj)
MaybeObject *(* getter)(Object *object, void *data)
Definition: v8globals.h:342
void LookupCallbackProperty(String *name, LookupResult *result)
Definition: objects.cc:4323
JSGlobalPropertyCell * GetPropertyCell(LookupResult *result)
Definition: objects.cc:12012
static MarkBit MarkBitFrom(Address addr)
MUST_USE_RESULT MaybeObject * AddNumberEntry(uint32_t key, Object *value)
Definition: objects.cc:12633
void set_dictionary_map(bool value)
Definition: objects-inl.h:3123
void Add(Vector< const char > format, Vector< FmtElm > elms)
void LookupDescriptor(JSObject *holder, String *name, LookupResult *result)
Definition: objects-inl.h:2061
Handle< Value >(* IndexedPropertyGetter)(uint32_t index, const AccessorInfo &info)
Definition: v8.h:2093
void IterateBody(InstanceType type, int object_size, ObjectVisitor *v)
Definition: objects.cc:1328
uint8_t byte
Definition: globals.h:156
virtual MUST_USE_RESULT MaybeObject * AsObject()=0
SmartArrayPointer< char > ToCString(AllowNullsFlag allow_nulls, RobustnessFlag robustness_flag, int offset, int length, int *length_output=0)
Definition: objects.cc:6233
MUST_USE_RESULT MaybeObject * SetPropertyWithCallback(Object *structure, String *name, Object *value, JSObject *holder, StrictModeFlag strict_mode)
Definition: objects.cc:1918
Object * ValueAt(int entry)
Definition: objects.h:3067
Object * InObjectPropertyAtPut(int index, Object *value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
Definition: objects-inl.h:1611
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11971
Map * GetTransition(int transition_index)
Definition: objects-inl.h:3707
bool IsMatch(Object *symbols)
Definition: objects.cc:12360
bool LookupSymbolIfExists(String *str, String **symbol)
Definition: objects.cc:12126
const uint16_t * SeqTwoByteStringGetData(unsigned start)
Definition: objects.cc:6340
void CopyFrom(int dst_index, DescriptorArray *src, int src_index, const WhitenessWitness &)
Definition: objects.cc:6068
static const int kMaxCachedPrototypeTransitions
Definition: objects.h:5111
MUST_USE_RESULT MaybeObject * LookupTwoByteSymbol(Vector< const uc16 > str, Object **s)
Definition: objects.cc:12179
void set_null(int index)
Definition: objects-inl.h:1888
UnicodeCache * unicode_cache()
Definition: isolate.h:870
MUST_USE_RESULT MaybeObject * GetIdentityHash(CreationFlag flag)
Definition: objects.cc:3558
void RemoveByIndex(Object *name, Code *code, int index)
Definition: objects.cc:5657
static uchar Length(uchar chr, int previous)
Definition: unicode-inl.h:124
static void NoWriteBarrierSet(FixedArray *array, int index, Object *value)
Definition: objects-inl.h:1864
static const uint32_t kMaxGap
Definition: objects.h:2151
String * GetKey(int descriptor_number)
Definition: objects-inl.h:2093
TwoByteSymbolKey(Vector< const uc16 > str, uint32_t seed)
Definition: objects.cc:11255
MUST_USE_RESULT MaybeObject * GetIdentityHash(CreationFlag flag)
Definition: objects-inl.h:5080
bool IsMatch(Object *other)
Definition: objects.cc:10967
static const int kTransitionSize
Definition: transitions.h:163
void CopyEnumCacheFrom(DescriptorArray *array)
Definition: objects.h:2524
static void DeoptimizeGlobalObject(JSObject *object)
Definition: deoptimizer.cc:262
static const int kLiteralNativeContextIndex
Definition: objects.h:6195
virtual size_t length() const =0
void Iterate(ObjectVisitor *v)
Definition: objects.cc:1319
uint32_t HashForObject(Object *other)
Definition: objects.cc:11159
#define UNREACHABLE()
Definition: checks.h:50
void SetOptimizing(BailoutId osr_ast_id)
Definition: compiler.h:152
Handle< Value >(* NamedPropertyGetter)(Local< String > property, const AccessorInfo &info)
Definition: v8.h:2053
virtual MUST_USE_RESULT MaybeObject * AddElementsToFixedArray(Object *receiver, JSObject *holder, FixedArray *to, FixedArrayBase *from=NULL)=0
MUST_USE_RESULT MaybeObject * GetLocalPropertyPostInterceptor(Object *receiver, String *name, PropertyAttributes *attributes)
Definition: objects.cc:10468
MUST_USE_RESULT MaybeObject * SetFastElement(uint32_t index, Object *value, StrictModeFlag strict_mode, bool check_prototype)
Definition: objects.cc:9495
static void Update(Handle< PolymorphicCodeCache > cache, MapHandleList *maps, Code::Flags flags, Handle< Code > code)
Definition: objects.cc:5782
T * start() const
Definition: utils.h:390
MUST_USE_RESULT MaybeObject * AllocateUninitializedFixedDoubleArray(int length, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:4866
static void PrintTop(FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:754
PolymorphicCodeCacheHashTableKey(MapHandleList *maps, int code_flags)
Definition: objects.cc:5837
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
static SeededNumberDictionary * cast(Object *obj)
Definition: objects.h:3236
void Append(Descriptor *desc, const WhitenessWitness &)
Definition: objects-inl.h:2205
virtual const char * NameOfCPURegister(int reg) const
bool MarkAsUndetectable()
Definition: objects.cc:7146
void LookupRealNamedPropertyInPrototypes(String *name, LookupResult *result)
Definition: objects.cc:2432
int NumberOfElementsFilterAttributes(PropertyAttributes filter)
Definition: objects.cc:12704
MUST_USE_RESULT MaybeObject * AddConstantFunctionProperty(String *name, JSFunction *function, PropertyAttributes attributes)
Definition: objects.cc:1604
MUST_USE_RESULT MaybeObject * AddFastProperty(String *name, Object *value, PropertyAttributes attributes, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:1537
IntrusiveMapTransitionIterator(TransitionArray *transition_array)
Definition: objects.cc:5318
bool IsStringObjectWithCharacterAt(uint32_t index)
Definition: objects-inl.h:1701
#define MUST_USE_RESULT
Definition: globals.h:346
void InstallFromOptimizedCodeMap(JSFunction *function, int index)
Definition: objects.cc:7626
bool IsFastPackedElementsKind(ElementsKind kind)
MUST_USE_RESULT MaybeObject * Put(FixedArray *key, Map *value)
Definition: objects.cc:12397
virtual void Seek(unsigned)
Definition: unicode.cc:352
void set_undefined(int index)
Definition: objects-inl.h:1874
static SlicedString * cast(Object *obj)
static ExternalIntArray * cast(Object *obj)
static const int kProtoTransitionMapOffset
Definition: objects.h:4906
SymbolKey(String *string)
Definition: objects.cc:11272
MUST_USE_RESULT MaybeObject * SetPrototypeTransitions(FixedArray *prototype_transitions)
Definition: objects-inl.h:3729
static void AddToOptimizedCodeMap(Handle< SharedFunctionInfo > shared, Handle< Context > native_context, Handle< Code > code, Handle< FixedArray > literals)
Definition: objects.cc:7583
MUST_USE_RESULT MaybeObject * SetElementsLength(Object *length)
Definition: objects.cc:8931
void set_expected_nof_properties(int value)
void SetNumberOfProtoTransitions(int value)
Definition: objects.h:4915
void SetNumberOfElements(int nof)
Definition: objects.h:2897
MUST_USE_RESULT MaybeObject * SetElementWithHandler(JSReceiver *receiver, uint32_t index, Object *value, StrictModeFlag strict_mode)
Definition: objects.cc:267
Handle< Integer >(* NamedPropertyQuery)(Local< String > property, const AccessorInfo &info)
Definition: v8.h:2070
MUST_USE_RESULT MaybeObject * SetFastDoubleElement(uint32_t index, Object *value, StrictModeFlag strict_mode, bool check_prototype=true)
Definition: objects.cc:9756
Context * native_context()
Definition: contexts.cc:58
static uint32_t MapsHashHelper(MapHandleList *maps, int code_flags)
Definition: objects.cc:5868
void IteratePointers(ObjectVisitor *v, int start, int end)
Definition: objects-inl.h:1187
MUST_USE_RESULT MaybeObject * AddEntry(Key key, Object *value, PropertyDetails details, uint32_t hash)
Definition: objects.cc:12576
static bool IsValidElementsTransition(ElementsKind from_kind, ElementsKind to_kind)
Definition: objects.cc:10148
static const uchar kMaxNonSurrogateCharCode
Definition: unicode.h:133
void GetLocalPropertyNames(FixedArray *storage, int index)
Definition: objects.cc:10750
static Failure * cast(MaybeObject *object)
Definition: objects-inl.h:496
#define CALL_HEAP_FUNCTION(ISOLATE, FUNCTION_CALL, TYPE)
Definition: heap-inl.h:558
void ResetForNewContext(int new_ic_age)
Definition: objects.cc:8134
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11992
bool ToArrayIndex(uint32_t *index)
Definition: objects-inl.h:1682
ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number)
void SetElementsCapacityAndLength(Handle< JSArray > array, int capacity, int length)
Definition: factory.cc:963
ElementsKind GetElementsKind()
Definition: objects-inl.h:4776
byte * instruction_start()
Definition: objects-inl.h:4649
static Object * RawUninitializedSentinel(Heap *heap)
Definition: objects-inl.h:5349
static Handle< Map > GetElementsTransitionMap(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:2329
MUST_USE_RESULT MaybeObject * AllocateFixedArrayWithHoles(int length, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:4827
const int kPointerSize
Definition: globals.h:220
#define MAKE_STRUCT_CASE(NAME, Name, name)
static const int kMaxCachedArrayIndexLength
Definition: objects.h:7349
MUST_USE_RESULT MaybeObject * ShareDescriptor(DescriptorArray *descriptors, Descriptor *descriptor)
Definition: objects.cc:4954
Object * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11858
MUST_USE_RESULT MaybeObject * DeleteElement(uint32_t index, DeleteMode mode)
Definition: objects.cc:3991
static const char *const kTags[kNumberOfSyncTags]
Definition: objects.h:8862
static const int kIsNotArrayIndexMask
Definition: objects.h:7337
uint32_t HashForObject(Key key, Object *object)
Definition: objects.h:2791
FixedArray * CopyEnumKeysTo(FixedArray *storage)
Definition: objects.cc:12752
static Oddball * cast(Object *obj)
static PolymorphicCodeCacheHashTable * cast(Object *obj)
static Address & Address_at(Address addr)
Definition: v8memory.h:71
FlatStringReader(Isolate *isolate, Handle< String > str)
Definition: objects.cc:6645
static const int kMaxInstanceSize
Definition: objects.h:2164
int GetFieldIndex(int descriptor_number)
Definition: objects-inl.h:2141
const int kHeapObjectTag
Definition: v8.h:4009
static const uint32_t kRequiresSlowElementsLimit
Definition: objects.h:3277
Handle< Integer >(* IndexedPropertyQuery)(uint32_t index, const AccessorInfo &info)
Definition: v8.h:2110
MUST_USE_RESULT MaybeObject * GenerateNewEnumerationIndices()
Definition: objects.cc:12434
MUST_USE_RESULT MaybeObject * PutPrototypeTransition(Object *prototype, Map *map)
Definition: objects.cc:8955
void LookupRealNamedProperty(String *name, LookupResult *result)
Definition: objects.cc:2424
static SeqAsciiString * cast(Object *obj)
void set_inobject_properties(int value)
Definition: objects-inl.h:2995
Handle< Object > GetSourceCode()
Definition: objects.cc:7827
MUST_USE_RESULT MaybeObject * AddProperty(String *name, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED, ExtensibilityCheck extensibility_check=PERFORM_EXTENSIBILITY_CHECK)
Definition: objects.cc:1671
void set_hash_field(uint32_t value)
Definition: objects-inl.h:2411
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11923
V8EXPORT int32_t Int32Value() const
Definition: api.cc:2662
MUST_USE_RESULT MaybeObject * CopyAddDescriptor(Descriptor *descriptor, TransitionFlag flag)
Definition: objects.cc:5142
void(* AccessorSetter)(Local< String > property, Local< Value > value, const AccessorInfo &info)
Definition: v8.h:1452
static ExternalUnsignedByteArray * cast(Object *obj)
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
static const int kProtoTransitionNumberOfEntriesOffset
Definition: objects.h:4903
static void TransformToFastProperties(Handle< JSObject > object, int unused_property_fields)
Definition: objects.cc:3392
static int TimeInDay(int64_t time_ms, int days)
Definition: date.h:85
uint32_t HashForObject(Object *other)
Definition: objects.cc:11229
static unsigned decode(uint32_t value)
Definition: utils.h:273
void SetCapacity(int capacity)
Definition: objects.h:2907
MUST_USE_RESULT MaybeObject * set_initial_map_and_cache_transitions(Map *value)
Definition: objects-inl.h:4415
bool ShouldConvertToFastDoubleElements(bool *has_smi_only_elements)
Definition: objects.cc:10361
static Handle< Object > SetLocalPropertyIgnoreAttributes(Handle< JSObject > object, Handle< String > key, Handle< Object > value, PropertyAttributes attributes)
Definition: objects.cc:2952
const Register pc
Vector< const uc16 > ToUC16Vector()
Definition: objects.h:7145
MUST_USE_RESULT MaybeObject * SetPropertyPostInterceptor(String *name, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode, ExtensibilityCheck extensibility_check)
Definition: objects.cc:1716
uint32_t FindInsertionEntry(uint32_t hash)
Definition: objects.cc:11484
SafepointEntry GetSafepointEntry(Address pc)
Definition: objects.cc:8388
int length() const
Definition: utils.h:384
static const int kPropertiesOffset
Definition: objects.h:2171
static void EnsureDescriptorSlack(Handle< Map > map, int slack)
Definition: objects.cc:2170
T RoundUp(T x, intptr_t m)
Definition: utils.h:150
#define CALL_AND_RETRY(ISOLATE, FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY)
Definition: heap-inl.h:523
#define ASSERT_LE(v1, v2)
Definition: checks.h:275
static FixedDoubleArray * cast(Object *obj)
static MUST_USE_RESULT Handle< Object > SetElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attr, StrictModeFlag strict_mode, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:9886
static const char * State2String(State state)
Definition: full-codegen.h:109
int GetIndex(Object *name, Code *code)
Definition: objects.cc:5641
Object * FastPropertyAt(int index)
Definition: objects-inl.h:1566
static ExternalPixelArray * cast(Object *obj)
static const int kSize
Definition: objects.h:5139
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:3559
bool is_inline_cache_stub()
Definition: objects-inl.h:3485
CodeCacheHashTableKey(String *name, Code::Flags flags)
Definition: objects.cc:5682
bool IsFastSmiElementsKind(ElementsKind kind)
MUST_USE_RESULT MaybeObject * CopyNormalized(PropertyNormalizationMode mode, NormalizedMapSharingMode sharing)
Definition: objects.cc:4909
Map * empty_object_map()
Definition: isolate.h:533
bool has_pending_exception()
Definition: isolate.h:561
MUST_USE_RESULT MaybeObject * SetFastElementsCapacityAndLength(int capacity, int length, SetFastElementsCapacitySmiMode smi_mode)
Definition: objects.cc:8789
FixedArray * GetEnumIndicesCache()
Definition: objects.h:2542
Object * FastPropertyAtPut(int index, Object *value)
Definition: objects-inl.h:1579
void set_kind(byte kind)
Definition: objects-inl.h:1463
static ElementsAccessor * ForArray(FixedArrayBase *array)
Definition: elements.cc:1573
static int GetOutputInfo(DeoptimizationOutputData *data, BailoutId node_id, SharedFunctionInfo *shared)
Definition: deoptimizer.cc:498
MUST_USE_RESULT MaybeObject * DeleteElementWithHandler(uint32_t index, DeleteMode mode)
Definition: objects.cc:2672
MUST_USE_RESULT MaybeObject * SetPropertyViaPrototypesWithHandler(JSReceiver *receiver, String *name, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode, bool *done)
Definition: objects.cc:2557
static int GetIdentityHash(Handle< JSObject > obj)
Definition: objects.cc:3531
static uint32_t NameFlagsHashHelper(String *name, Code::Flags flags)
Definition: objects.cc:5702
void CopyFrom(const CodeDesc &desc)
Definition: objects.cc:8291
bool HasRealNamedCallbackProperty(String *key)
Definition: objects.cc:10604
InterceptorInfo * GetNamedInterceptor()
Definition: objects.cc:10430
const unibrow::byte * ConsStringReadBlock(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6398
void SortPairs(FixedArray *numbers, uint32_t len)
Definition: objects.cc:10708
static const int kContainsCachedArrayIndexMask
Definition: objects.h:7374
WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation &)
Definition: objects-inl.h:1831
MUST_USE_RESULT MaybeObject * Shrink(Key key)
Definition: objects.cc:12523
int CompareChars(const lchar *lhs, const rchar *rhs, int chars)
Definition: utils.h:768
PropertyDetails GetDetails(int descriptor_number)
Definition: objects-inl.h:2129
int TenToThe(int exponent)
Definition: utils.h:795
virtual MUST_USE_RESULT MaybeObject * Get(Object *receiver, JSObject *holder, uint32_t key, FixedArrayBase *backing_store=NULL)=0
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11917
static bool ComputeArrayIndex(unibrow::CharacterStream *buffer, uint32_t *index, int length)
Definition: objects.cc:7245
TraversableMap * ChildIteratorNext()
Definition: objects.cc:5460
void SetNumberOfDeletedElements(int nod)
Definition: objects.h:2902
Failure * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:945
bool is_call_stub()
Definition: objects.h:4301
InlineCacheState ic_state()
Definition: objects-inl.h:3168
byte * relocation_start()
Definition: objects-inl.h:4675
Assembler * origin
Definition: v8globals.h:232
void set_construction_count(int value)
Definition: objects-inl.h:4040
double get_scalar(int index)
Definition: objects-inl.h:1783
Object * Lookup(Object *key)
Definition: objects.cc:13036
static uint32_t MakeArrayIndexHash(uint32_t value, int length)
Definition: objects.cc:7290
static MUST_USE_RESULT MaybeObject * Allocate(int at_least_space_for)
Handle< Map > FindTransitionedMap(MapHandleList *candidates)
Definition: objects.cc:2243
uint16_t ConsStringGet(int index)
Definition: objects.cc:6834
void Lookup(String *name, LookupResult *result)
Definition: objects.cc:4309
void set_map_no_write_barrier(Map *value)
Definition: objects-inl.h:1154
static Handle< Object > Call(Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Definition: execution.cc:150
bool LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String **symbol)
Definition: objects.cc:12140
MUST_USE_RESULT MaybeObject * Initialize(int capacity)
Definition: objects.cc:8909
virtual bool HasElement(Object *receiver, JSObject *holder, uint32_t key, FixedArrayBase *backing_store=NULL)=0
static unsigned Encode(char *out, uchar c, int previous)
Definition: unicode-inl.h:82
int Weekday(int days)
Definition: date.h:92
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
void SetTransition(int transition_index, Map *target)
Definition: objects-inl.h:3702
Object * SlowReverseLookup(Object *value)
Definition: objects.cc:12819
#define DECLARE_TAG(ignore1, name, ignore2)
Definition: objects.cc:8219
static JSArray * cast(Object *obj)
PropertyAttributes GetPropertyAttributeWithReceiver(JSReceiver *receiver, String *name)
Definition: objects.cc:3128
void HeapSortPairs(FixedArray *content, FixedArray *numbers, int len)
Definition: objects.cc:10661
#define T(name, string, precedence)
Definition: token.cc:48
static int SizeFor(int length)
Definition: objects.h:2353
static Object * GetField(Object *date, Smi *index)
Definition: objects.cc:13353
String * GetKey(int transition_number)
static const int kProtoTransitionHeaderSize
Definition: objects.h:4902
Context * context()
Definition: isolate.h:520
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
static JSDate * cast(Object *obj)
Definition: objects-inl.h:4618
void SetNextEnumerationIndex(int index)
Definition: objects.h:3113
static ElementsAccessor * ForKind(ElementsKind elements_kind)
Definition: elements.h:134
bool IsThisPropertyAssignmentArgument(int index)
Definition: objects.cc:7936
bool IsMatch(Object *string)
Definition: objects.cc:11258
static SeqTwoByteString * cast(Object *obj)
int PropertyIndexFor(String *name)
Definition: objects.cc:4231
const unibrow::byte * SeqAsciiStringReadBlock(unsigned *remaining, unsigned *offset, unsigned chars)
Definition: objects.cc:6379
LocalElementType HasLocalElement(uint32_t index)
Definition: objects.cc:9168
bool HasTransitionArray()
Definition: objects-inl.h:3675
static ExternalDoubleArray * cast(Object *obj)
bool IsTransitionableFastElementsKind(ElementsKind from_kind)
static void UpdateCodeCache(Handle< Map > map, Handle< String > name, Handle< Code > code)
Definition: objects.cc:5261
static const unibrow::byte * ReadBlock(String *input, unibrow::byte *util_buffer, unsigned capacity, unsigned *remaining, unsigned *offset)
Definition: objects.cc:6740
PropertyNormalizationMode
Definition: objects.h:153
static ExternalFloatArray * cast(Object *obj)
bool HasElementWithHandler(uint32_t index)
Definition: objects.cc:278
MUST_USE_RESULT MaybeObject * Put(String *name, Code *code)
Definition: objects.cc:5743
FlatContent GetFlatContent()
Definition: objects.cc:6191
void set(int index, double value)
Definition: objects-inl.h:1808
static const int kMaxShortPrintLength
Definition: objects.h:7393
static int SNPrintF(Vector< char > str, const char *format,...)
bool IsKey(Object *k)
Definition: objects.h:2845
MUST_USE_RESULT MaybeObject * NumberFromDouble(double value, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:3081
void PrintElementsKind(FILE *out, ElementsKind kind)
SimpleTransitionFlag
Definition: objects.h:184
MUST_USE_RESULT MaybeObject * SetFastDoubleElementsCapacityAndLength(int capacity, int length)
Definition: objects.cc:8855
uint32_t DoubleToUint32(double x)
Definition: conversions.h:101
uint32_t HashForObject(Object *other)
Definition: objects.cc:11105
bool IsMatch(Object *string)
Definition: objects.cc:11090
static const int kMapOffset
Definition: objects.h:1261
bool ShouldConvertToSlowElements(int new_capacity)
Definition: objects.cc:10308
int NumberOfDescribedProperties(DescriptorFlag which=OWN_DESCRIPTORS, PropertyAttributes filter=NONE)
Definition: objects.cc:4217
MUST_USE_RESULT MaybeObject * DeleteNormalizedProperty(String *name, DeleteMode mode)
Definition: objects.cc:518
int32_t DoubleToInt32(double x)
void LocalLookup(String *name, LookupResult *result)
Definition: objects.cc:4267
void IteratePrefix(ObjectVisitor *visitor)
Definition: objects.cc:11313
static HeapNumber * cast(Object *obj)
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
Definition: objects.cc:6891
MUST_USE_RESULT MaybeObject * NormalizeElements()
Definition: objects.cc:3416
static StringDictionary * cast(Object *obj)
Definition: objects.h:3182
void set_value(double value)
Definition: objects-inl.h:1203
virtual size_t length() const =0
static double nan_value()
bool is_compare_ic_stub()
Definition: objects.h:4305
void ExternalAsciiStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset, unsigned chars)
Definition: objects.cc:6522
MUST_USE_RESULT MaybeObject * AllocateAccessorPair()
Definition: heap.cc:2133
static ObjectHashTable * cast(Object *obj)
Definition: objects.h:3340
bool is_null() const
Definition: handles.h:87
#define STRUCT_LIST(V)
Definition: objects.h:448
static uint32_t RandomPrivate(Isolate *isolate)
Definition: v8.cc:181
int GetIndex(String *name, Code::Flags flags)
Definition: objects.cc:5766
AccessorDescriptor * GetCallbacks(int descriptor_number)
Definition: objects-inl.h:2157
MUST_USE_RESULT MaybeObject * SetPropertyWithHandler(JSReceiver *receiver, String *name, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: objects.cc:2537
InterceptorInfo * GetIndexedInterceptor()
Definition: objects.cc:10440
MUST_USE_RESULT MaybeObject * CopyWithPreallocatedFieldDescriptors()
Definition: objects.cc:5110
ExtraICState extra_ic_state()
Definition: objects-inl.h:3181
MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(JSReceiver *receiver, String *name)
Definition: objects.cc:2682
#define IS_POWER_OF_TWO(x)
Definition: utils.h:45
Map * GetTarget(int transition_number)
bool has_fast_smi_or_object_elements()
Definition: objects.h:4796
bool CanGenerateInlineConstructor(Object *prototype)
Definition: objects.cc:7855
PropertyType GetType(int descriptor_number)
Definition: objects-inl.h:2136
static JSGlobalPropertyCell * cast(Object *obj)
void YearMonthDayFromDays(int days, int *year, int *month, int *day)
Definition: date.cc:77
static Object * cast(Object *value)
Definition: objects.h:1007
MUST_USE_RESULT MaybeObject * NumberFromUint32(uint32_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: heap-inl.h:240
bool Contains(Address addr)
Definition: heap.cc:5367
StaticResource< StringInputBuffer > * objects_string_input_buffer()
Definition: isolate.h:908
static bool EnsureCompiled(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: objects.cc:7668
String * hidden_symbol()
Definition: heap.h:1184
static Handle< Object > DeleteProperty(Handle< JSObject > obj, Handle< String > name)
Definition: objects.cc:3926
void BecomeJSObject(Handle< JSReceiver > object)
Definition: factory.cc:1007
#define UNIMPLEMENTED()
Definition: checks.h:48
MUST_USE_RESULT MaybeObject * SetPropertyForResult(LookupResult *result, String *key, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode, StoreFromKeyed store_mode)
Definition: objects.cc:2805
static void ReadBlockIntoBuffer(String *input, ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned max_chars)
Definition: objects.cc:6690
static const uint32_t kHashBitMask
Definition: objects.h:7345
uint16_t uc16
Definition: globals.h:259
bool HasPropertyWithHandler(String *name)
Definition: objects.cc:2522
void SetNumberOfDescriptors(int number_of_descriptors)
Definition: objects-inl.h:1946
Object * GetBackPointer()
Definition: objects-inl.h:3659
void AddCharacterNoIndex(uint32_t c)
Definition: objects-inl.h:4995
void SlicedStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6881
void HeapObjectShortPrint(StringStream *accumulator)
Definition: objects.cc:1188
PropertyDetails DetailsAt(int entry)
Definition: objects.h:3077
uint32_t ComputeLongHash(uint64_t key)
Definition: utils.h:299
Object * DeleteProperty(int entry, JSObject::DeleteMode mode)
Definition: objects.cc:12508
MUST_USE_RESULT MaybeObject * SetDictionaryElement(uint32_t index, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode, bool check_prototype, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:9615
PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(Object *receiver, LookupResult *result, String *name, bool continue_search)
Definition: objects.cc:371
Handle< Object > NewTypeError(const char *type, Vector< Handle< Object > > args)
Definition: factory.cc:630
Handle< SharedFunctionInfo > shared_info() const
Definition: compiler.h:71
MUST_USE_RESULT MaybeObject * SetPropertyWithInterceptor(String *name, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: objects.cc:1850
void set_bit_field(byte value)
Definition: objects-inl.h:3034
static Token::Value ComputeOperation(Code *target)
Definition: ic.cc:2579
static const int kMaxNumberOfDescriptors
Definition: objects.h:2665
SymbolsKey(FixedArray *symbols)
Definition: objects.cc:12358
virtual const char * data() const =0
static JSReceiver * cast(Object *obj)
MUST_USE_RESULT MaybeObject * Initialize(const char *to_string, Object *to_number, byte kind)
Definition: objects.cc:7799
ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind, bool allow_only_packed)
static JSValue * cast(Object *obj)
Definition: objects-inl.h:4600
Vector< const Char > string_
Definition: objects.cc:11163
uint32_t HashSequentialString(const schar *chars, int length, uint32_t seed)
Definition: objects-inl.h:5013
bool ShouldConvertToFastElements()
Definition: objects.cc:10328
static const int kArrayIndexHashLengthShift
Definition: objects.h:7361
static const int kFieldsAdded
Definition: objects.h:2168
static const int kMaxUncheckedOldFastElementsLength
Definition: objects.h:2159
MUST_USE_RESULT MaybeObject * DefineFastAccessor(String *name, AccessorComponent component, Object *accessor, PropertyAttributes attributes)
Definition: objects.cc:4651
void ValueAtPut(int entry, Object *value)
Definition: objects.h:3072
void set(int index, double value)
Definition: objects-inl.h:2921
MUST_USE_RESULT MaybeObject * AsObject()
Definition: objects.cc:5887
uint32_t HashForObject(Object *obj)
Definition: objects.cc:5708
static Handle< T > null()
Definition: handles.h:86
void MemsetPointer(T **dest, U *value, int counter)
Definition: v8utils.h:149
MaybeObject * AsObject()
Definition: objects.cc:11285
bool is_keyed_store_stub()
Definition: objects.h:4300
Object * LookupEval(String *src, Context *context, LanguageMode language_mode, int scope_position)
Definition: objects.cc:12243
MUST_USE_RESULT MaybeObject * CopyAsElementsKind(ElementsKind kind, TransitionFlag flag)
Definition: objects.cc:5058
Map * FindFirstMap()
Definition: objects.cc:8401
int Search(T *array, String *name, int valid_entries)
Definition: objects-inl.h:2016
static const int kProtoTransitionPrototypeOffset
Definition: objects.h:4905
static MUST_USE_RESULT MaybeObject * Allocate(int number_of_descriptors, int slack=0)
Definition: objects.cc:6032
static void IncrementLiveBytesFromMutator(Address address, int by)
Definition: spaces.cc:769
#define HEAP
Definition: isolate.h:1433
virtual void Seek(unsigned pos)
Definition: objects.cc:6681
MUST_USE_RESULT MaybeObject * GetPropertyWithHandler(Object *receiver, String *name)
Definition: objects.cc:234
Object * Lookup(String *name, Code::Flags flags)
Definition: objects.cc:5735
static const int kInitialSize
Definition: objects.h:6836
MUST_USE_RESULT MaybeObject * GetProperty(String *key)
Definition: objects-inl.h:859
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
bool is_dictionary_map()
Definition: objects-inl.h:3128
void SetInstanceClassName(String *name)
Definition: objects.cc:7783
SubStringAsciiSymbolKey(Handle< SeqAsciiString > string, int from, int length, uint32_t seed)
Definition: objects.cc:11188
Object * extension()
Definition: contexts.h:318
const int kShortSize
Definition: globals.h:216
void set_owns_descriptors(bool is_shared)
Definition: objects-inl.h:3143
static bool CompileLazy(Handle< SharedFunctionInfo > shared, ClearExceptionFlag flag)
Definition: objects.cc:7570
MUST_USE_RESULT MaybeObject * Add(Object *key)
Definition: objects.cc:12990
InstanceType instance_type()
Definition: objects-inl.h:3009
MUST_USE_RESULT MaybeObject * AllocateJSGlobalPropertyCell(Object *value)
Definition: heap.cc:2519
static JSProxy * cast(Object *obj)
void SetIdentityHash(Handle< JSObject > object, Smi *hash)
Definition: factory.cc:1023
void SetParent(TraversableMap *parent)
Definition: objects.cc:5437
Handle< String > Uint32ToString(uint32_t value)
Definition: factory.cc:1082
static State ComputeState(Code *target)
Definition: ic.cc:2571
static bool ShouldZapGarbage()
Definition: heap.h:1287
bool MayIndexedAccess(JSObject *receiver, uint32_t index, v8::AccessType type)
Definition: isolate.cc:878
Object * Lookup(String *src, Context *context)
Definition: objects.cc:12231
static Handle< Object > ToNumber(Handle< Object > obj, bool *exc)
Definition: execution.cc:634
void USE(T)
Definition: globals.h:289
int NumberOfProtoTransitions()
Definition: objects.h:4908
Counters * counters()
Definition: isolate.h:819
MUST_USE_RESULT MaybeObject * OptimizeAsPrototype()
Definition: objects.cc:7688
static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size)
Definition: objects.h:2927
void EnableDeoptimizationSupport(Code *recompiled)
Definition: objects.cc:8015
bool TooManyFastProperties(int properties, StoreFromKeyed store_mode)
Definition: objects-inl.h:1655
#define ASSERT_NE(v1, v2)
Definition: checks.h:272
static AccessorInfo * cast(Object *obj)
virtual void Rewind()=0
static FixedArray * cast(Object *obj)
MUST_USE_RESULT MaybeObject * CopyUpTo(int enumeration_index)
Definition: objects.cc:5203
static const int kHeaderSize
Definition: objects.h:2173
static Smi * set(Smi *smi, int bit_position, bool v)
Definition: objects.h:8948
bool IsCompatibleReceiver(Object *receiver)
Definition: objects-inl.h:5135
Object * SetNormalizedProperty(LookupResult *result, Object *value)
Definition: objects.cc:445
static HashTable * cast(Object *obj)
Definition: objects-inl.h:2394
void set_is_extensible(bool value)
Definition: objects-inl.h:3087
static bool CompileLazy(CompilationInfo *info)
Definition: compiler.cc:786
ElementsKind elements_kind()
Definition: objects.h:4781
MUST_USE_RESULT MaybeObject * AtNumberPut(uint32_t key, Object *value)
Definition: objects.cc:12646
Object * GetHiddenProperty(String *key)
Definition: objects.cc:3568
void set_is_shared(bool value)
Definition: objects-inl.h:3113
static const int kEntryLength
Definition: objects.h:5403
static Handle< Object > GetElement(Handle< Object > object, uint32_t index)
Definition: objects.cc:250
static Handle< Object > PreventExtensions(Handle< JSObject > object)
Definition: objects.cc:4138
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:38
bool IsEmpty() const
Definition: v8.h:209
FixedArray * GetEnumCache()
Definition: objects.h:2528
#define FACTORY
Definition: isolate.h:1434
static const int kArrayIndexValueBits
Definition: objects.h:7354
MUST_USE_RESULT MaybeObject * RawCopy(int instance_size)
Definition: objects.cc:4889
StaticResource< Utf8Decoder > * utf8_decoder()
Definition: scanner.h:150
static void NormalizeProperties(Handle< JSObject > object, PropertyNormalizationMode mode, int expected_additional_properties)
Definition: objects.cc:3275
const uint32_t kMaxUInt32
Definition: globals.h:213
MUST_USE_RESULT MaybeObject * NumberFromInt32(int32_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: heap-inl.h:232
static Handle< JSGlobalPropertyCell > EnsurePropertyCell(Handle< GlobalObject > global, Handle< String > name)
Definition: objects.cc:12019
void SetEntry(int entry, Object *key, Object *value)
Definition: objects-inl.h:5143
static const int kFlagsIndex
Definition: objects.h:6630
MUST_USE_RESULT MaybeObject * AddSlowProperty(String *name, Object *value, PropertyAttributes attributes)
Definition: objects.cc:1634
Object * GetCallbacksObject(int descriptor_number)
Definition: objects-inl.h:2151
void Reset(Input input)
Definition: unicode-inl.h:233
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if NULL
Definition: flags.cc:301
Object * get(int index)
Definition: objects-inl.h:1737
int GetThisPropertyAssignmentArgument(int index)
Definition: objects.cc:7945
static VisitorId GetVisitorId(int instance_type, int instance_size)
int FindEntry(String *key)
Definition: objects.cc:11351
bool IsFastHoleyElementsKind(ElementsKind kind)
#define BUILTIN(name)
Definition: builtins.cc:142
static MUST_USE_RESULT Handle< SeededNumberDictionary > Set(Handle< SeededNumberDictionary > dictionary, uint32_t index, Handle< Object > value, PropertyDetails details)
Definition: objects.cc:12652
void IterateElements(ObjectVisitor *visitor)
Definition: objects.cc:11319
CodeCacheHashTableKey(String *name, Code *code)
Definition: objects.cc:5685
MUST_USE_RESULT MaybeObject * Put(Object *key, Object *value)
Definition: objects.cc:13051
ElementsAccessor * GetElementsAccessor()
Definition: objects-inl.h:4799
Utf8SymbolKey(Vector< const char > string, uint32_t seed)
Definition: objects.cc:11087
MUST_USE_RESULT MaybeObject * JSArrayUpdateLengthFromIndex(uint32_t index, Object *value)
Definition: objects.cc:10161
void OutputToFile(FILE *out)
static const int kAttachedToSharedFunctionInfo
Definition: objects.h:5178
MUST_USE_RESULT MaybeObject * SetPrototype(Object *value, bool skip_hidden_prototypes)
Definition: objects.cc:9014
String * TryFlattenGetString(PretenureFlag pretenure=NOT_TENURED)
Definition: objects-inl.h:2436
bool HasFastArgumentsElements()
Definition: objects.cc:9468
MUST_USE_RESULT MaybeObject * LookupString(String *key, Object **s)
Definition: objects.cc:12056
void set_bit_field2(byte value)
Definition: objects-inl.h:3044
static MUST_USE_RESULT MaybeObject * AsObject(uint32_t key)
Definition: objects-inl.h:5195
static void UpdateMapCodeCache(Handle< JSObject > object, Handle< String > name, Handle< Code > code)
Definition: objects.cc:3248
void CreateFillerObjectAt(Address addr, int size)
Definition: heap.cc:3558
void SwapPairs(FixedArray *numbers, int i, int j)
Definition: objects.cc:10634
AsciiSymbolKey(Vector< const char > str, uint32_t seed)
Definition: objects.cc:11172
void set(AccessorComponent component, Object *value)
Definition: objects.h:8445
void set(int index, uint8_t value)
Definition: objects-inl.h:2757
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
static const int kMaxCapacity
Definition: objects.h:2879
static int Decode(FILE *f, byte *begin, byte *end)
static uint32_t RegExpHash(String *string, Smi *flags)
Definition: objects.cc:11076
JSFunction * closure()
Definition: contexts.h:307
int NumberOfLocalProperties(PropertyAttributes filter=NONE)
Definition: objects.cc:10620
int GetSortedKeyIndex(int descriptor_number)
Definition: objects-inl.h:2099
static void FlushICache(void *start, size_t size)
bool IsEqualTo(Vector< const char > str)
Definition: objects.cc:7163
static ExternalByteArray * cast(Object *obj)
MUST_USE_RESULT MaybeObject * AtPut(Key key, Object *value)
Definition: objects.cc:12529
static const int kMaxUncheckedFastElementsLength
Definition: objects.h:2155
Definition: objects.h:6953
Handle< Boolean >(* IndexedPropertyDeleter)(uint32_t index, const AccessorInfo &info)
Definition: v8.h:2118
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: v8utils.h:117
const int kMaxKeyedPolymorphism
Definition: type-info.h:39
static Flags RemoveTypeFromFlags(Flags flags)
Definition: objects-inl.h:3553
void LocalLookupRealNamedProperty(String *name, LookupResult *result)
Definition: objects.cc:2375
static int DaysFromTime(int64_t time_ms)
Definition: date.h:77
bool is_keyed_call_stub()
Definition: objects.h:4302
V8EXPORT bool IsInt32() const
Definition: api.cc:2205
int aliased_context_slot()
void JSFunctionIterateBody(int object_size, ObjectVisitor *v)
Definition: objects.cc:7526
void set_this_property_assignments_count(int value)
const uint32_t kAsciiStringTag
Definition: objects.h:470
Object ** GetKeySlot(int transition_number)
void CopyChars(sinkchar *dest, const sourcechar *src, int chars)
Definition: v8utils.h:211
String * GetThisPropertyAssignmentName(int index)
Definition: objects.cc:7926
static const int kConstructStubOffset
Definition: objects.h:5799
static const int kHashShift
Definition: objects.h:7341
AccessorDescriptor * FindAccessor(String *name)
Definition: objects.cc:4255
MUST_USE_RESULT MaybeObject * DeleteProperty(String *name, DeleteMode mode)
Definition: objects.cc:3999
static bool EncodeAsciiCharacter(uchar c, byte *buffer, unsigned capacity, unsigned &offset)
Definition: unicode-inl.h:162
MUST_USE_RESULT MaybeObject * Shrink(Key key)
Definition: objects.cc:11453
MUST_USE_RESULT MaybeObject * GetHash(CreationFlag flag)
Definition: objects.cc:756
static uint32_t FirstProbe(uint32_t hash, uint32_t size)
Definition: objects.h:2923
static const char * GetStateName(State state)
Definition: ic.cc:2586
static ConsString * cast(Object *obj)
uint32_t HashForObject(Object *obj)
Definition: objects.cc:11009
bool HasDictionaryArgumentsElements()
Definition: objects.cc:9480
void JSObjectShortPrint(StringStream *accumulator)
Definition: objects.cc:1087
static CodeCache * cast(Object *obj)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting 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 more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage including flags
Definition: flags.cc:495
static int NewElementsCapacity(int old_capacity)
Definition: objects.h:1806
bool IsIdentifierStart(unibrow::uchar c)
Definition: scanner.h:154
static FixedArrayBase * cast(Object *object)
Definition: objects-inl.h:1731
unsigned char byte
Definition: unicode.h:41
MUST_USE_RESULT MaybeObject * LookupSymbol(Vector< const char > str, Object **s)
Definition: objects.cc:12156
static Context * NativeContextFromLiterals(FixedArray *literals)
Definition: objects.cc:7794
void StringShortPrint(StringStream *accumulator)
Definition: objects.cc:1024
void ClearNonLiveTransitions(Heap *heap)
Definition: objects.cc:7426
Object * GetComponent(AccessorComponent component)
Definition: objects.cc:6150
uint32_t HashForObject(Object *key)
Definition: objects.cc:12107
static const int kMaxValue
Definition: objects.h:1050
int NextFreePropertyIndex()
Definition: objects.cc:4241
static const int kCodeCacheOffset
Definition: objects.h:5136
const unibrow::byte * SlicedStringReadBlock(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6870
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11950
static ExternalUnsignedIntArray * cast(Object *obj)
static MUST_USE_RESULT MaybeObject * Allocate(int number_of_deopt_points, PretenureFlag pretenure)
Definition: objects.cc:6164
static const int kNotFound
Definition: objects.h:2619
static void DefineAccessor(Handle< JSObject > object, Handle< String > name, Handle< Object > getter, Handle< Object > setter, PropertyAttributes attributes)
Definition: objects.cc:4576
void set_non_instance_prototype(bool value)
Definition: objects-inl.h:3049
virtual MUST_USE_RESULT MaybeObject * SetLength(JSArray *holder, Object *new_length)=0
const uc32 kMaxAsciiCharCode
Definition: globals.h:263
MUST_USE_RESULT MaybeObject * Remove(Object *key)
Definition: objects.cc:13017
void SetTarget(int transition_number, Map *target)
Handle< Value >(* AccessorGetter)(Local< String > property, const AccessorInfo &info)
Definition: v8.h:1448
MUST_USE_RESULT MaybeObject * CopyReplaceDescriptor(DescriptorArray *descriptors, Descriptor *descriptor, int index, TransitionFlag flag)
Definition: objects.cc:5223
MUST_USE_RESULT MaybeObject * AllocateMap(InstanceType instance_type, int instance_size, ElementsKind elements_kind=TERMINAL_FAST_ELEMENTS_KIND)
Definition: heap.cc:2085
Handle< Object > NewNumberFromUint(uint32_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:613
MUST_USE_RESULT MaybeObject * Copy()
Definition: objects.cc:6138
#define ARRAY_SIZE(a)
Definition: globals.h:281
StringDictionary * property_dictionary()
Definition: objects-inl.h:4899
const int kCharSize
Definition: globals.h:215
MUST_USE_RESULT MaybeObject * AsObject()
Definition: objects.cc:11023
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
MUST_USE_RESULT MaybeObject * CopySize(int new_length)
Definition: objects.cc:5989
void TraverseTransitionTree(TraverseCallback callback, void *data)
Definition: objects.cc:5490
void SetNoStackCheckTable()
Definition: objects.cc:8394
MUST_USE_RESULT MaybeObject * ReplaceSlowProperty(String *name, Object *value, PropertyAttributes attributes)
Definition: objects.cc:1742
void UpdateMaxNumberKey(uint32_t key)
Definition: objects.cc:12605
static MUST_USE_RESULT MaybeObject * Allocate(int at_least_space_for, MinimumCapacity capacity_option=USE_DEFAULT_MINIMUM_CAPACITY, PretenureFlag pretenure=NOT_TENURED)
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11944
void InitializeDescriptors(DescriptorArray *descriptors)
Definition: objects-inl.h:3608
FixedArray * GetPrototypeTransitions()
Definition: objects-inl.h:3720
static void AddFastPropertyUsingMap(Handle< JSObject > object, Handle< Map > map)
Definition: objects.cc:2797
static ObjectHashSet * cast(Object *obj)
Definition: objects.h:3320
static JSObject * cast(Object *obj)
void ClearInlineCaches()
Definition: objects.cc:8414
static const int kMaxArrayIndexSize
Definition: objects.h:7324
static const char *const kTagNames[kNumberOfSyncTags]
Definition: objects.h:8863
static void Clear(Address address)
Definition: ic.cc:344
MarkCompactCollector * mark_compact_collector()
Definition: heap.h:1541
PropertyAttributes GetLocalPropertyAttribute(String *name)
Definition: objects.cc:3179
static const int kNoPreviousCharacter
Definition: unicode.h:132
void BecomeJSFunction(Handle< JSReceiver > object)
Definition: factory.cc:1015
MUST_USE_RESULT MaybeObject * GetPropertyPostInterceptor(Object *receiver, String *name, PropertyAttributes *attributes)
Definition: objects.cc:10450
static InterceptorInfo * cast(Object *obj)
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11930
bool IsFastDoubleElementsKind(ElementsKind kind)
MUST_USE_RESULT MaybeObject * EnsureCanContainElements(Object **elements, uint32_t count, EnsureElementsMode mode)
Definition: objects-inl.h:1268
MUST_USE_RESULT MaybeObject * SubString(int from, int to, PretenureFlag pretenure=NOT_TENURED)
Definition: objects.cc:7363
void set_unused_property_fields(int value)
Definition: objects-inl.h:3024
bool is_keyed_load_stub()
Definition: objects.h:4298
Object * FindInCodeCache(String *name, Code::Flags flags)
Definition: objects.cc:5287
const uint32_t kStringEncodingMask
Definition: objects.h:468
Object * Lookup(FixedArray *key)
Definition: objects.cc:12389
MUST_USE_RESULT MaybeObject * AtNumberPut(uint32_t key, Object *value)
Definition: objects.cc:12640
static MUST_USE_RESULT Handle< UnseededNumberDictionary > Set(Handle< UnseededNumberDictionary > dictionary, uint32_t index, Handle< Object > value)
Definition: objects.cc:12663
void SetComponents(Object *getter, Object *setter)
Definition: objects.h:8457
void DisableOptimization(const char *reason)
Definition: objects.cc:8034
void set_stack_check_table_offset(unsigned offset)
Definition: objects-inl.h:3358
Handle< Boolean >(* NamedPropertyDeleter)(Local< String > property, const AccessorInfo &info)
Definition: v8.h:2079
void set_bit_field3(int value)
static DeoptimizationInputData * cast(Object *obj)
int64_t ToLocal(int64_t time_ms)
Definition: date.h:126
Object * GetThisPropertyAssignmentConstant(int index)
Definition: objects.cc:7953
MUST_USE_RESULT MaybeObject * AllocateAliasedArgumentsEntry(int slot)
Definition: heap.cc:2156
IntrusivePrototypeTransitionIterator(HeapObject *proto_trans)
Definition: objects.cc:5362
String * constructor_name()
Definition: objects.cc:1487
bool IsAsciiEqualTo(Vector< const char > str)
Definition: objects.cc:7184
Handle< JSObject > Copy(Handle< JSObject > obj)
Definition: handles.cc:335
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset kInstanceClassNameOffset flag
Definition: objects-inl.h:3923
static JSGlobalObject * cast(Object *obj)
void StartInobjectSlackTracking(Map *map)
Definition: objects.cc:8067
static JSFunction * cast(Object *obj)