v8  3.11.10(node0.8.26)
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* global_context) {
73  if (IsNumber()) {
74  return CreateJSValue(global_context->number_function(), this);
75  } else if (IsBoolean()) {
76  return CreateJSValue(global_context->boolean_function(), this);
77  } else if (IsString()) {
78  return CreateJSValue(global_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* global_context = isolate->context()->global_context();
91  return CreateJSValue(global_context->number_function(), this);
92  } else if (IsBoolean()) {
93  Isolate* isolate = HeapObject::cast(this)->GetIsolate();
94  Context* global_context = isolate->context()->global_context();
95  return CreateJSValue(global_context->boolean_function(), this);
96  } else if (IsString()) {
97  Isolate* isolate = HeapObject::cast(this)->GetIsolate();
98  Context* global_context = isolate->context()->global_context();
99  return CreateJSValue(global_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* global_context = Isolate::Current()->context()->global_context();
138  if (IsNumber()) {
139  holder = global_context->number_function()->instance_prototype();
140  } else if (IsString()) {
141  holder = global_context->string_function()->instance_prototype();
142  } else if (IsBoolean()) {
143  holder = global_context->boolean_function()->instance_prototype();
144  }
145  }
146  ASSERT(holder != NULL); // Cannot handle null or undefined.
147  JSReceiver::cast(holder)->Lookup(name, result);
148 }
149 
150 
152  String* name,
153  PropertyAttributes* attributes) {
154  LookupResult result(name->GetIsolate());
155  Lookup(name, &result);
156  MaybeObject* value = GetProperty(receiver, &result, name, attributes);
157  ASSERT(*attributes <= ABSENT);
158  return value;
159 }
160 
161 
163  Object* structure,
164  String* name) {
165  Isolate* isolate = name->GetIsolate();
166  // To accommodate both the old and the new api we switch on the
167  // data structure used to store the callbacks. Eventually foreign
168  // callbacks should be phased out.
169  if (structure->IsForeign()) {
170  AccessorDescriptor* callback =
171  reinterpret_cast<AccessorDescriptor*>(
172  Foreign::cast(structure)->foreign_address());
173  MaybeObject* value = (callback->getter)(receiver, callback->data);
175  return value;
176  }
177 
178  // api style callbacks.
179  if (structure->IsAccessorInfo()) {
180  AccessorInfo* data = AccessorInfo::cast(structure);
181  if (!data->IsCompatibleReceiver(receiver)) {
182  Handle<Object> name_handle(name);
183  Handle<Object> receiver_handle(receiver);
184  Handle<Object> args[2] = { name_handle, receiver_handle };
185  Handle<Object> error =
186  isolate->factory()->NewTypeError("incompatible_method_receiver",
187  HandleVector(args,
188  ARRAY_SIZE(args)));
189  return isolate->Throw(*error);
190  }
191  Object* fun_obj = data->getter();
192  v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
193  HandleScope scope(isolate);
194  JSObject* self = JSObject::cast(receiver);
195  Handle<String> key(name);
196  LOG(isolate, ApiNamedPropertyAccess("load", self, name));
197  CustomArguments args(isolate, data->data(), self, this);
198  v8::AccessorInfo info(args.end());
199  v8::Handle<v8::Value> result;
200  {
201  // Leaving JavaScript.
202  VMState state(isolate, EXTERNAL);
203  result = call_fun(v8::Utils::ToLocal(key), info);
204  }
206  if (result.IsEmpty()) {
207  return isolate->heap()->undefined_value();
208  }
209  return *v8::Utils::OpenHandle(*result);
210  }
211 
212  // __defineGetter__ callback
213  if (structure->IsAccessorPair()) {
214  Object* getter = AccessorPair::cast(structure)->getter();
215  if (getter->IsSpecFunction()) {
216  // TODO(rossberg): nicer would be to cast to some JSCallable here...
217  return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
218  }
219  // Getter is not a function.
220  return isolate->heap()->undefined_value();
221  }
222 
223  UNREACHABLE();
224  return NULL;
225 }
226 
227 
228 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
229  String* name_raw) {
230  Isolate* isolate = GetIsolate();
231  HandleScope scope(isolate);
232  Handle<Object> receiver(receiver_raw);
233  Handle<Object> name(name_raw);
234 
235  Handle<Object> args[] = { receiver, name };
236  Handle<Object> result = CallTrap(
237  "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
238  if (isolate->has_pending_exception()) return Failure::Exception();
239 
240  return *result;
241 }
242 
243 
245  Isolate* isolate = object->IsHeapObject()
246  ? Handle<HeapObject>::cast(object)->GetIsolate()
247  : Isolate::Current();
248  CALL_HEAP_FUNCTION(isolate, object->GetElement(index), Object);
249 }
250 
251 
252 MaybeObject* JSProxy::GetElementWithHandler(Object* receiver,
253  uint32_t index) {
254  String* name;
255  MaybeObject* maybe = GetHeap()->Uint32ToString(index);
256  if (!maybe->To<String>(&name)) return maybe;
257  return GetPropertyWithHandler(receiver, name);
258 }
259 
260 
262  uint32_t index,
263  Object* value,
264  StrictModeFlag strict_mode) {
265  String* name;
266  MaybeObject* maybe = GetHeap()->Uint32ToString(index);
267  if (!maybe->To<String>(&name)) return maybe;
268  return SetPropertyWithHandler(receiver, name, value, NONE, strict_mode);
269 }
270 
271 
272 bool JSProxy::HasElementWithHandler(uint32_t index) {
273  String* name;
274  MaybeObject* maybe = GetHeap()->Uint32ToString(index);
275  if (!maybe->To<String>(&name)) return maybe;
276  return HasPropertyWithHandler(name);
277 }
278 
279 
281  JSReceiver* getter) {
282  HandleScope scope;
283  Handle<JSReceiver> fun(getter);
284  Handle<Object> self(receiver);
285 #ifdef ENABLE_DEBUGGER_SUPPORT
286  Debug* debug = fun->GetHeap()->isolate()->debug();
287  // Handle stepping into a getter if step into is active.
288  // TODO(rossberg): should this apply to getters that are function proxies?
289  if (debug->StepInActive() && fun->IsJSFunction()) {
290  debug->HandleStepIn(
292  }
293 #endif
294 
295  bool has_pending_exception;
296  Handle<Object> result =
297  Execution::Call(fun, self, 0, NULL, &has_pending_exception, true);
298  // Check for pending exception and return the result.
299  if (has_pending_exception) return Failure::Exception();
300  return *result;
301 }
302 
303 
304 // Only deal with CALLBACKS and INTERCEPTOR
306  Object* receiver,
307  LookupResult* result,
308  String* name,
309  PropertyAttributes* attributes) {
310  if (result->IsProperty()) {
311  switch (result->type()) {
312  case CALLBACKS: {
313  // Only allow API accessors.
314  Object* obj = result->GetCallbackObject();
315  if (obj->IsAccessorInfo()) {
316  AccessorInfo* info = AccessorInfo::cast(obj);
317  if (info->all_can_read()) {
318  *attributes = result->GetAttributes();
319  return result->holder()->GetPropertyWithCallback(
320  receiver, result->GetCallbackObject(), name);
321  }
322  }
323  break;
324  }
325  case NORMAL:
326  case FIELD:
327  case CONSTANT_FUNCTION: {
328  // Search ALL_CAN_READ accessors in prototype chain.
329  LookupResult r(GetIsolate());
330  result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
331  if (r.IsProperty()) {
332  return GetPropertyWithFailedAccessCheck(receiver,
333  &r,
334  name,
335  attributes);
336  }
337  break;
338  }
339  case INTERCEPTOR: {
340  // If the object has an interceptor, try real named properties.
341  // No access check in GetPropertyAttributeWithInterceptor.
342  LookupResult r(GetIsolate());
343  result->holder()->LookupRealNamedProperty(name, &r);
344  if (r.IsProperty()) {
345  return GetPropertyWithFailedAccessCheck(receiver,
346  &r,
347  name,
348  attributes);
349  }
350  break;
351  }
352  default:
353  UNREACHABLE();
354  }
355  }
356 
357  // No accessible property found.
358  *attributes = ABSENT;
359  Heap* heap = name->GetHeap();
361  return heap->undefined_value();
362 }
363 
364 
366  Object* receiver,
367  LookupResult* result,
368  String* name,
369  bool continue_search) {
370  if (result->IsProperty()) {
371  switch (result->type()) {
372  case CALLBACKS: {
373  // Only allow API accessors.
374  Object* obj = result->GetCallbackObject();
375  if (obj->IsAccessorInfo()) {
376  AccessorInfo* info = AccessorInfo::cast(obj);
377  if (info->all_can_read()) {
378  return result->GetAttributes();
379  }
380  }
381  break;
382  }
383 
384  case NORMAL:
385  case FIELD:
386  case CONSTANT_FUNCTION: {
387  if (!continue_search) break;
388  // Search ALL_CAN_READ accessors in prototype chain.
389  LookupResult r(GetIsolate());
390  result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
391  if (r.IsProperty()) {
393  &r,
394  name,
395  continue_search);
396  }
397  break;
398  }
399 
400  case INTERCEPTOR: {
401  // If the object has an interceptor, try real named properties.
402  // No access check in GetPropertyAttributeWithInterceptor.
403  LookupResult r(GetIsolate());
404  if (continue_search) {
405  result->holder()->LookupRealNamedProperty(name, &r);
406  } else {
407  result->holder()->LocalLookupRealNamedProperty(name, &r);
408  }
409  if (r.IsProperty()) {
411  &r,
412  name,
413  continue_search);
414  }
415  break;
416  }
417 
418  default:
419  UNREACHABLE();
420  }
421  }
422 
424  return ABSENT;
425 }
426 
427 
428 Object* JSObject::GetNormalizedProperty(LookupResult* result) {
430  Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
431  if (IsGlobalObject()) {
432  value = JSGlobalPropertyCell::cast(value)->value();
433  }
434  ASSERT(!value->IsJSGlobalPropertyCell());
435  return value;
436 }
437 
438 
439 Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) {
441  if (IsGlobalObject()) {
442  JSGlobalPropertyCell* cell =
444  property_dictionary()->ValueAt(result->GetDictionaryEntry()));
445  cell->set_value(value);
446  } else {
447  property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
448  }
449  return value;
450 }
451 
452 
454  Handle<String> key,
455  Handle<Object> value,
456  PropertyDetails details) {
457  CALL_HEAP_FUNCTION(object->GetIsolate(),
458  object->SetNormalizedProperty(*key, *value, details),
459  Object);
460 }
461 
462 
464  Object* value,
465  PropertyDetails details) {
467  int entry = property_dictionary()->FindEntry(name);
468  if (entry == StringDictionary::kNotFound) {
469  Object* store_value = value;
470  if (IsGlobalObject()) {
471  Heap* heap = name->GetHeap();
472  MaybeObject* maybe_store_value =
473  heap->AllocateJSGlobalPropertyCell(value);
474  if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
475  }
476  Object* dict;
477  { MaybeObject* maybe_dict =
478  property_dictionary()->Add(name, store_value, details);
479  if (!maybe_dict->ToObject(&dict)) return maybe_dict;
480  }
481  set_properties(StringDictionary::cast(dict));
482  return value;
483  }
484  // Preserve enumeration index.
485  details = PropertyDetails(details.attributes(),
486  details.type(),
487  property_dictionary()->DetailsAt(entry).index());
488  if (IsGlobalObject()) {
489  JSGlobalPropertyCell* cell =
491  cell->set_value(value);
492  // Please note we have to update the property details.
493  property_dictionary()->DetailsAtPut(entry, details);
494  } else {
495  property_dictionary()->SetEntry(entry, name, value, details);
496  }
497  return value;
498 }
499 
500 
503  StringDictionary* dictionary = property_dictionary();
504  int entry = dictionary->FindEntry(name);
505  if (entry != StringDictionary::kNotFound) {
506  // If we have a global object set the cell to the hole.
507  if (IsGlobalObject()) {
508  PropertyDetails details = dictionary->DetailsAt(entry);
509  if (details.IsDontDelete()) {
510  if (mode != FORCE_DELETION) return GetHeap()->false_value();
511  // When forced to delete global properties, we have to make a
512  // map change to invalidate any ICs that think they can load
513  // from the DontDelete cell without checking if it contains
514  // the hole value.
515  Object* new_map;
516  { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
517  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
518  }
519  set_map(Map::cast(new_map));
520  }
521  JSGlobalPropertyCell* cell =
522  JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
523  cell->set_value(cell->GetHeap()->the_hole_value());
524  dictionary->DetailsAtPut(entry, details.AsDeleted());
525  } else {
526  Object* deleted = dictionary->DeleteProperty(entry, mode);
527  if (deleted == GetHeap()->true_value()) {
528  FixedArray* new_properties = NULL;
529  MaybeObject* maybe_properties = dictionary->Shrink(name);
530  if (!maybe_properties->To(&new_properties)) {
531  return maybe_properties;
532  }
533  set_properties(new_properties);
534  }
535  return deleted;
536  }
537  }
538  return GetHeap()->true_value();
539 }
540 
541 
543  Object* cons_obj = map()->constructor();
544  if (!cons_obj->IsJSFunction())
545  return true;
546  JSFunction* fun = JSFunction::cast(cons_obj);
547  if (!fun->shared()->IsApiFunction())
548  return true;
549  // If the object is fully fast case and has the same map it was
550  // created with then no changes can have been made to it.
551  return map() != fun->initial_map()
553  || !HasFastProperties();
554 }
555 
556 
558  Handle<Object> receiver,
559  LookupResult* result,
560  Handle<String> key,
561  PropertyAttributes* attributes) {
562  Isolate* isolate = object->IsHeapObject()
563  ? Handle<HeapObject>::cast(object)->GetIsolate()
564  : Isolate::Current();
566  isolate,
567  object->GetProperty(*receiver, result, *key, attributes),
568  Object);
569 }
570 
571 
572 MaybeObject* Object::GetProperty(Object* receiver,
573  LookupResult* result,
574  String* name,
575  PropertyAttributes* attributes) {
576  // Make sure that the top context does not change when doing
577  // callbacks or interceptor calls.
578  AssertNoContextChange ncc;
579  Heap* heap = name->GetHeap();
580 
581  // Traverse the prototype chain from the current object (this) to
582  // the holder and check for access rights. This avoids traversing the
583  // objects more than once in case of interceptors, because the
584  // holder will always be the interceptor holder and the search may
585  // only continue with a current object just after the interceptor
586  // holder in the prototype chain.
587  // Proxy handlers do not use the proxy's prototype, so we can skip this.
588  if (!result->IsHandler()) {
589  Object* last = result->IsProperty()
590  ? result->holder()
591  : Object::cast(heap->null_value());
592  ASSERT(this != this->GetPrototype());
593  for (Object* current = this; true; current = current->GetPrototype()) {
594  if (current->IsAccessCheckNeeded()) {
595  // Check if we're allowed to read from the current object. Note
596  // that even though we may not actually end up loading the named
597  // property from the current object, we still check that we have
598  // access to it.
599  JSObject* checked = JSObject::cast(current);
600  if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
601  return checked->GetPropertyWithFailedAccessCheck(receiver,
602  result,
603  name,
604  attributes);
605  }
606  }
607  // Stop traversing the chain once we reach the last object in the
608  // chain; either the holder of the result or null in case of an
609  // absent property.
610  if (current == last) break;
611  }
612  }
613 
614  if (!result->IsProperty()) {
615  *attributes = ABSENT;
616  return heap->undefined_value();
617  }
618  *attributes = result->GetAttributes();
619  Object* value;
620  switch (result->type()) {
621  case NORMAL:
622  value = result->holder()->GetNormalizedProperty(result);
623  ASSERT(!value->IsTheHole() || result->IsReadOnly());
624  return value->IsTheHole() ? heap->undefined_value() : value;
625  case FIELD:
626  value = result->holder()->FastPropertyAt(result->GetFieldIndex());
627  ASSERT(!value->IsTheHole() || result->IsReadOnly());
628  return value->IsTheHole() ? heap->undefined_value() : value;
629  case CONSTANT_FUNCTION:
630  return result->GetConstantFunction();
631  case CALLBACKS:
632  return result->holder()->GetPropertyWithCallback(
633  receiver, result->GetCallbackObject(), name);
634  case HANDLER:
635  return result->proxy()->GetPropertyWithHandler(receiver, name);
636  case INTERCEPTOR: {
637  JSObject* recvr = JSObject::cast(receiver);
638  return result->holder()->GetPropertyWithInterceptor(
639  recvr, name, attributes);
640  }
641  case MAP_TRANSITION:
642  case CONSTANT_TRANSITION:
643  case NULL_DESCRIPTOR:
644  break;
645  }
646  UNREACHABLE();
647  return NULL;
648 }
649 
650 
651 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
652  Heap* heap = IsSmi()
653  ? Isolate::Current()->heap()
654  : HeapObject::cast(this)->GetHeap();
655  Object* holder = this;
656 
657  // Iterate up the prototype chain until an element is found or the null
658  // prototype is encountered.
659  for (holder = this;
660  holder != heap->null_value();
661  holder = holder->GetPrototype()) {
662  if (!holder->IsJSObject()) {
663  Isolate* isolate = heap->isolate();
664  Context* global_context = isolate->context()->global_context();
665  if (holder->IsNumber()) {
666  holder = global_context->number_function()->instance_prototype();
667  } else if (holder->IsString()) {
668  holder = global_context->string_function()->instance_prototype();
669  } else if (holder->IsBoolean()) {
670  holder = global_context->boolean_function()->instance_prototype();
671  } else if (holder->IsJSProxy()) {
672  return JSProxy::cast(holder)->GetElementWithHandler(receiver, index);
673  } else {
674  // Undefined and null have no indexed properties.
675  ASSERT(holder->IsUndefined() || holder->IsNull());
676  return heap->undefined_value();
677  }
678  }
679 
680  // Inline the case for JSObjects. Doing so significantly improves the
681  // performance of fetching elements where checking the prototype chain is
682  // necessary.
683  JSObject* js_object = JSObject::cast(holder);
684 
685  // Check access rights if needed.
686  if (js_object->IsAccessCheckNeeded()) {
687  Isolate* isolate = heap->isolate();
688  if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
689  isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
690  return heap->undefined_value();
691  }
692  }
693 
694  if (js_object->HasIndexedInterceptor()) {
695  return js_object->GetElementWithInterceptor(receiver, index);
696  }
697 
698  if (js_object->elements() != heap->empty_fixed_array()) {
699  MaybeObject* result = js_object->GetElementsAccessor()->Get(
700  receiver, js_object, index);
701  if (result != heap->the_hole_value()) return result;
702  }
703  }
704 
705  return heap->undefined_value();
706 }
707 
708 
710  if (IsSmi()) {
711  Heap* heap = Isolate::Current()->heap();
712  Context* context = heap->isolate()->context()->global_context();
713  return context->number_function()->instance_prototype();
714  }
715 
716  HeapObject* heap_object = HeapObject::cast(this);
717 
718  // The object is either a number, a string, a boolean,
719  // a real JS object, or a Harmony proxy.
720  if (heap_object->IsJSReceiver()) {
721  return heap_object->map()->prototype();
722  }
723  Heap* heap = heap_object->GetHeap();
724  Context* context = heap->isolate()->context()->global_context();
725 
726  if (heap_object->IsHeapNumber()) {
727  return context->number_function()->instance_prototype();
728  }
729  if (heap_object->IsString()) {
730  return context->string_function()->instance_prototype();
731  }
732  if (heap_object->IsBoolean()) {
733  return context->boolean_function()->instance_prototype();
734  } else {
735  return heap->null_value();
736  }
737 }
738 
739 
741  // The object is either a number, a string, an odd-ball,
742  // a real JS object, or a Harmony proxy.
743  if (IsNumber()) {
744  uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
745  return Smi::FromInt(hash & Smi::kMaxValue);
746  }
747  if (IsString()) {
748  uint32_t hash = String::cast(this)->Hash();
749  return Smi::FromInt(hash);
750  }
751  if (IsOddball()) {
752  uint32_t hash = Oddball::cast(this)->to_string()->Hash();
753  return Smi::FromInt(hash);
754  }
755  if (IsJSReceiver()) {
756  return JSReceiver::cast(this)->GetIdentityHash(flag);
757  }
758 
759  UNREACHABLE();
760  return Smi::FromInt(0);
761 }
762 
763 
764 bool Object::SameValue(Object* other) {
765  if (other == this) return true;
766  if (!IsHeapObject() || !other->IsHeapObject()) return false;
767 
768  // The object is either a number, a string, an odd-ball,
769  // a real JS object, or a Harmony proxy.
770  if (IsNumber() && other->IsNumber()) {
771  double this_value = Number();
772  double other_value = other->Number();
773  return (this_value == other_value) ||
774  (isnan(this_value) && isnan(other_value));
775  }
776  if (IsString() && other->IsString()) {
777  return String::cast(this)->Equals(String::cast(other));
778  }
779  return false;
780 }
781 
782 
783 void Object::ShortPrint(FILE* out) {
784  HeapStringAllocator allocator;
785  StringStream accumulator(&allocator);
786  ShortPrint(&accumulator);
787  accumulator.OutputToFile(out);
788 }
789 
790 
791 void Object::ShortPrint(StringStream* accumulator) {
792  if (IsSmi()) {
793  Smi::cast(this)->SmiPrint(accumulator);
794  } else if (IsFailure()) {
795  Failure::cast(this)->FailurePrint(accumulator);
796  } else {
797  HeapObject::cast(this)->HeapObjectShortPrint(accumulator);
798  }
799 }
800 
801 
802 void Smi::SmiPrint(FILE* out) {
803  PrintF(out, "%d", value());
804 }
805 
806 
807 void Smi::SmiPrint(StringStream* accumulator) {
808  accumulator->Add("%d", value());
809 }
810 
811 
813  accumulator->Add("Failure(%p)", reinterpret_cast<void*>(value()));
814 }
815 
816 
817 void Failure::FailurePrint(FILE* out) {
818  PrintF(out, "Failure(%p)", reinterpret_cast<void*>(value()));
819 }
820 
821 
822 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
823 // English? Returns false for non-ASCII or words that don't start with
824 // a capital letter. The a/an rule follows pronunciation in English.
825 // We don't use the BBC's overcorrect "an historic occasion" though if
826 // you speak a dialect you may well say "an 'istoric occasion".
827 static bool AnWord(String* str) {
828  if (str->length() == 0) return false; // A nothing.
829  int c0 = str->Get(0);
830  int c1 = str->length() > 1 ? str->Get(1) : 0;
831  if (c0 == 'U') {
832  if (c1 > 'Z') {
833  return true; // An Umpire, but a UTF8String, a U.
834  }
835  } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
836  return true; // An Ape, an ABCBook.
837  } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
838  (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
839  c0 == 'S' || c0 == 'X')) {
840  return true; // An MP3File, an M.
841  }
842  return false;
843 }
844 
845 
846 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) {
847 #ifdef DEBUG
848  // Do not attempt to flatten in debug mode when allocation is not
849  // allowed. This is to avoid an assertion failure when allocating.
850  // Flattening strings is the only case where we always allow
851  // allocation because no GC is performed if the allocation fails.
852  if (!HEAP->IsAllocationAllowed()) return this;
853 #endif
854 
855  Heap* heap = GetHeap();
856  switch (StringShape(this).representation_tag()) {
857  case kConsStringTag: {
858  ConsString* cs = ConsString::cast(this);
859  if (cs->second()->length() == 0) {
860  return cs->first();
861  }
862  // There's little point in putting the flat string in new space if the
863  // cons string is in old space. It can never get GCed until there is
864  // an old space GC.
865  PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
866  int len = length();
867  Object* object;
868  String* result;
869  if (IsAsciiRepresentation()) {
870  { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure);
871  if (!maybe_object->ToObject(&object)) return maybe_object;
872  }
873  result = String::cast(object);
874  String* first = cs->first();
875  int first_length = first->length();
876  char* dest = SeqAsciiString::cast(result)->GetChars();
877  WriteToFlat(first, dest, 0, first_length);
878  String* second = cs->second();
879  WriteToFlat(second,
880  dest + first_length,
881  0,
882  len - first_length);
883  } else {
884  { MaybeObject* maybe_object =
885  heap->AllocateRawTwoByteString(len, tenure);
886  if (!maybe_object->ToObject(&object)) return maybe_object;
887  }
888  result = String::cast(object);
889  uc16* dest = SeqTwoByteString::cast(result)->GetChars();
890  String* first = cs->first();
891  int first_length = first->length();
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  }
899  cs->set_first(result);
900  cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER);
901  return result;
902  }
903  default:
904  return this;
905  }
906 }
907 
908 
910  // Externalizing twice leaks the external resource, so it's
911  // prohibited by the API.
912  ASSERT(!this->IsExternalString());
913 #ifdef DEBUG
915  // Assert that the resource and the string are equivalent.
916  ASSERT(static_cast<size_t>(this->length()) == resource->length());
917  ScopedVector<uc16> smart_chars(this->length());
918  String::WriteToFlat(this, smart_chars.start(), 0, this->length());
919  ASSERT(memcmp(smart_chars.start(),
920  resource->data(),
921  resource->length() * sizeof(smart_chars[0])) == 0);
922  }
923 #endif // DEBUG
924  Heap* heap = GetHeap();
925  int size = this->Size(); // Byte size of the original string.
926  if (size < ExternalString::kShortSize) {
927  return false;
928  }
929  bool is_ascii = this->IsAsciiRepresentation();
930  bool is_symbol = this->IsSymbol();
931 
932  // Morph the object to an external string by adjusting the map and
933  // reinitializing the fields.
934  if (size >= ExternalString::kSize) {
936  is_symbol
937  ? (is_ascii ? heap->external_symbol_with_ascii_data_map()
938  : heap->external_symbol_map())
939  : (is_ascii ? heap->external_string_with_ascii_data_map()
940  : heap->external_string_map()));
941  } else {
943  is_symbol
944  ? (is_ascii ? heap->short_external_symbol_with_ascii_data_map()
945  : heap->short_external_symbol_map())
946  : (is_ascii ? heap->short_external_string_with_ascii_data_map()
947  : heap->short_external_string_map()));
948  }
950  self->set_resource(resource);
951  if (is_symbol) self->Hash(); // Force regeneration of the hash value.
952 
953  // Fill the remainder of the string with dead wood.
954  int new_size = this->Size(); // Byte size of the external String object.
955  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
958  new_size - size);
959  }
960  return true;
961 }
962 
963 
965 #ifdef DEBUG
967  // Assert that the resource and the string are equivalent.
968  ASSERT(static_cast<size_t>(this->length()) == resource->length());
969  ScopedVector<char> smart_chars(this->length());
970  String::WriteToFlat(this, smart_chars.start(), 0, this->length());
971  ASSERT(memcmp(smart_chars.start(),
972  resource->data(),
973  resource->length() * sizeof(smart_chars[0])) == 0);
974  }
975 #endif // DEBUG
976  Heap* heap = GetHeap();
977  int size = this->Size(); // Byte size of the original string.
978  if (size < ExternalString::kShortSize) {
979  return false;
980  }
981  bool is_symbol = this->IsSymbol();
982 
983  // Morph the object to an external string by adjusting the map and
984  // reinitializing the fields. Use short version if space is limited.
985  if (size >= ExternalString::kSize) {
987  is_symbol ? heap->external_ascii_symbol_map()
988  : heap->external_ascii_string_map());
989  } else {
991  is_symbol ? heap->short_external_ascii_symbol_map()
992  : heap->short_external_ascii_string_map());
993  }
995  self->set_resource(resource);
996  if (is_symbol) self->Hash(); // Force regeneration of the hash value.
997 
998  // Fill the remainder of the string with dead wood.
999  int new_size = this->Size(); // Byte size of the external String object.
1000  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1003  new_size - size);
1004  }
1005  return true;
1006 }
1007 
1008 
1010  int len = length();
1011  if (len > kMaxShortPrintLength) {
1012  accumulator->Add("<Very long string[%u]>", len);
1013  return;
1014  }
1015 
1016  if (!LooksValid()) {
1017  accumulator->Add("<Invalid String>");
1018  return;
1019  }
1020 
1021  StringInputBuffer buf(this);
1022 
1023  bool truncated = false;
1024  if (len > kMaxShortPrintLength) {
1025  len = kMaxShortPrintLength;
1026  truncated = true;
1027  }
1028  bool ascii = true;
1029  for (int i = 0; i < len; i++) {
1030  int c = buf.GetNext();
1031 
1032  if (c < 32 || c >= 127) {
1033  ascii = false;
1034  }
1035  }
1036  buf.Reset(this);
1037  if (ascii) {
1038  accumulator->Add("<String[%u]: ", length());
1039  for (int i = 0; i < len; i++) {
1040  accumulator->Put(buf.GetNext());
1041  }
1042  accumulator->Put('>');
1043  } else {
1044  // Backslash indicates that the string contains control
1045  // characters and that backslashes are therefore escaped.
1046  accumulator->Add("<String[%u]\\: ", length());
1047  for (int i = 0; i < len; i++) {
1048  int c = buf.GetNext();
1049  if (c == '\n') {
1050  accumulator->Add("\\n");
1051  } else if (c == '\r') {
1052  accumulator->Add("\\r");
1053  } else if (c == '\\') {
1054  accumulator->Add("\\\\");
1055  } else if (c < 32 || c > 126) {
1056  accumulator->Add("\\x%02x", c);
1057  } else {
1058  accumulator->Put(c);
1059  }
1060  }
1061  if (truncated) {
1062  accumulator->Put('.');
1063  accumulator->Put('.');
1064  accumulator->Put('.');
1065  }
1066  accumulator->Put('>');
1067  }
1068  return;
1069 }
1070 
1071 
1073  switch (map()->instance_type()) {
1074  case JS_ARRAY_TYPE: {
1075  double length = JSArray::cast(this)->length()->IsUndefined()
1076  ? 0
1077  : JSArray::cast(this)->length()->Number();
1078  accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1079  break;
1080  }
1081  case JS_WEAK_MAP_TYPE: {
1082  accumulator->Add("<JS WeakMap>");
1083  break;
1084  }
1085  case JS_REGEXP_TYPE: {
1086  accumulator->Add("<JS RegExp>");
1087  break;
1088  }
1089  case JS_FUNCTION_TYPE: {
1090  Object* fun_name = JSFunction::cast(this)->shared()->name();
1091  bool printed = false;
1092  if (fun_name->IsString()) {
1093  String* str = String::cast(fun_name);
1094  if (str->length() > 0) {
1095  accumulator->Add("<JS Function ");
1096  accumulator->Put(str);
1097  accumulator->Put('>');
1098  printed = true;
1099  }
1100  }
1101  if (!printed) {
1102  accumulator->Add("<JS Function>");
1103  }
1104  break;
1105  }
1106  // All other JSObjects are rather similar to each other (JSObject,
1107  // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1108  default: {
1109  Map* map_of_this = map();
1110  Heap* heap = GetHeap();
1111  Object* constructor = map_of_this->constructor();
1112  bool printed = false;
1113  if (constructor->IsHeapObject() &&
1114  !heap->Contains(HeapObject::cast(constructor))) {
1115  accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1116  } else {
1117  bool global_object = IsJSGlobalProxy();
1118  if (constructor->IsJSFunction()) {
1119  if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1120  accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1121  } else {
1123  JSFunction::cast(constructor)->shared()->name();
1124  if (constructor_name->IsString()) {
1125  String* str = String::cast(constructor_name);
1126  if (str->length() > 0) {
1127  bool vowel = AnWord(str);
1128  accumulator->Add("<%sa%s ",
1129  global_object ? "Global Object: " : "",
1130  vowel ? "n" : "");
1131  accumulator->Put(str);
1132  printed = true;
1133  }
1134  }
1135  }
1136  }
1137  if (!printed) {
1138  accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1139  }
1140  }
1141  if (IsJSValue()) {
1142  accumulator->Add(" value = ");
1143  JSValue::cast(this)->value()->ShortPrint(accumulator);
1144  }
1145  accumulator->Put('>');
1146  break;
1147  }
1148  }
1149 }
1150 
1151 
1153  FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
1154  ElementsKind to_kind, FixedArrayBase* to_elements) {
1155  if (from_kind != to_kind) {
1156  PrintF(file, "elements transition [");
1157  PrintElementsKind(file, from_kind);
1158  PrintF(file, " -> ");
1159  PrintElementsKind(file, to_kind);
1160  PrintF(file, "] in ");
1161  JavaScriptFrame::PrintTop(file, false, true);
1162  PrintF(file, " for ");
1163  ShortPrint(file);
1164  PrintF(file, " from ");
1165  from_elements->ShortPrint(file);
1166  PrintF(file, " to ");
1167  to_elements->ShortPrint(file);
1168  PrintF(file, "\n");
1169  }
1170 }
1171 
1172 
1174  Heap* heap = GetHeap();
1175  if (!heap->Contains(this)) {
1176  accumulator->Add("!!!INVALID POINTER!!!");
1177  return;
1178  }
1179  if (!heap->Contains(map())) {
1180  accumulator->Add("!!!INVALID MAP!!!");
1181  return;
1182  }
1183 
1184  accumulator->Add("%p ", this);
1185 
1186  if (IsString()) {
1187  String::cast(this)->StringShortPrint(accumulator);
1188  return;
1189  }
1190  if (IsJSObject()) {
1191  JSObject::cast(this)->JSObjectShortPrint(accumulator);
1192  return;
1193  }
1194  switch (map()->instance_type()) {
1195  case MAP_TYPE:
1196  accumulator->Add("<Map(elements=%u)>", Map::cast(this)->elements_kind());
1197  break;
1198  case FIXED_ARRAY_TYPE:
1199  accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
1200  break;
1202  accumulator->Add("<FixedDoubleArray[%u]>",
1203  FixedDoubleArray::cast(this)->length());
1204  break;
1205  case BYTE_ARRAY_TYPE:
1206  accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
1207  break;
1208  case FREE_SPACE_TYPE:
1209  accumulator->Add("<FreeSpace[%u]>", FreeSpace::cast(this)->Size());
1210  break;
1212  accumulator->Add("<ExternalPixelArray[%u]>",
1213  ExternalPixelArray::cast(this)->length());
1214  break;
1216  accumulator->Add("<ExternalByteArray[%u]>",
1217  ExternalByteArray::cast(this)->length());
1218  break;
1220  accumulator->Add("<ExternalUnsignedByteArray[%u]>",
1221  ExternalUnsignedByteArray::cast(this)->length());
1222  break;
1224  accumulator->Add("<ExternalShortArray[%u]>",
1225  ExternalShortArray::cast(this)->length());
1226  break;
1228  accumulator->Add("<ExternalUnsignedShortArray[%u]>",
1229  ExternalUnsignedShortArray::cast(this)->length());
1230  break;
1232  accumulator->Add("<ExternalIntArray[%u]>",
1233  ExternalIntArray::cast(this)->length());
1234  break;
1236  accumulator->Add("<ExternalUnsignedIntArray[%u]>",
1237  ExternalUnsignedIntArray::cast(this)->length());
1238  break;
1240  accumulator->Add("<ExternalFloatArray[%u]>",
1241  ExternalFloatArray::cast(this)->length());
1242  break;
1244  accumulator->Add("<ExternalDoubleArray[%u]>",
1245  ExternalDoubleArray::cast(this)->length());
1246  break;
1248  accumulator->Add("<SharedFunctionInfo>");
1249  break;
1251  accumulator->Add("<JSMessageObject>");
1252  break;
1253 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1254  case NAME##_TYPE: \
1255  accumulator->Put('<'); \
1256  accumulator->Add(#Name); \
1257  accumulator->Put('>'); \
1258  break;
1260 #undef MAKE_STRUCT_CASE
1261  case CODE_TYPE:
1262  accumulator->Add("<Code>");
1263  break;
1264  case ODDBALL_TYPE: {
1265  if (IsUndefined())
1266  accumulator->Add("<undefined>");
1267  else if (IsTheHole())
1268  accumulator->Add("<the hole>");
1269  else if (IsNull())
1270  accumulator->Add("<null>");
1271  else if (IsTrue())
1272  accumulator->Add("<true>");
1273  else if (IsFalse())
1274  accumulator->Add("<false>");
1275  else
1276  accumulator->Add("<Odd Oddball>");
1277  break;
1278  }
1279  case HEAP_NUMBER_TYPE:
1280  accumulator->Add("<Number: ");
1281  HeapNumber::cast(this)->HeapNumberPrint(accumulator);
1282  accumulator->Put('>');
1283  break;
1284  case JS_PROXY_TYPE:
1285  accumulator->Add("<JSProxy>");
1286  break;
1288  accumulator->Add("<JSFunctionProxy>");
1289  break;
1290  case FOREIGN_TYPE:
1291  accumulator->Add("<Foreign>");
1292  break;
1294  accumulator->Add("Cell for ");
1295  JSGlobalPropertyCell::cast(this)->value()->ShortPrint(accumulator);
1296  break;
1297  default:
1298  accumulator->Add("<Other heap object (%d)>", map()->instance_type());
1299  break;
1300  }
1301 }
1302 
1303 
1304 void HeapObject::Iterate(ObjectVisitor* v) {
1305  // Handle header
1307  // Handle object body
1308  Map* m = map();
1309  IterateBody(m->instance_type(), SizeFromMap(m), v);
1310 }
1311 
1312 
1314  ObjectVisitor* v) {
1315  // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1316  // During GC, the map pointer field is encoded.
1317  if (type < FIRST_NONSTRING_TYPE) {
1318  switch (type & kStringRepresentationMask) {
1319  case kSeqStringTag:
1320  break;
1321  case kConsStringTag:
1323  break;
1324  case kSlicedStringTag:
1326  break;
1327  case kExternalStringTag:
1328  if ((type & kStringEncodingMask) == kAsciiStringTag) {
1329  reinterpret_cast<ExternalAsciiString*>(this)->
1330  ExternalAsciiStringIterateBody(v);
1331  } else {
1332  reinterpret_cast<ExternalTwoByteString*>(this)->
1333  ExternalTwoByteStringIterateBody(v);
1334  }
1335  break;
1336  }
1337  return;
1338  }
1339 
1340  switch (type) {
1341  case FIXED_ARRAY_TYPE:
1342  FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1343  break;
1345  break;
1346  case JS_OBJECT_TYPE:
1348  case JS_MODULE_TYPE:
1349  case JS_VALUE_TYPE:
1350  case JS_DATE_TYPE:
1351  case JS_ARRAY_TYPE:
1352  case JS_SET_TYPE:
1353  case JS_MAP_TYPE:
1354  case JS_WEAK_MAP_TYPE:
1355  case JS_REGEXP_TYPE:
1356  case JS_GLOBAL_PROXY_TYPE:
1357  case JS_GLOBAL_OBJECT_TYPE:
1360  JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1361  break;
1362  case JS_FUNCTION_TYPE:
1363  reinterpret_cast<JSFunction*>(this)
1364  ->JSFunctionIterateBody(object_size, v);
1365  break;
1366  case ODDBALL_TYPE:
1368  break;
1369  case JS_PROXY_TYPE:
1371  break;
1374  break;
1375  case FOREIGN_TYPE:
1376  reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1377  break;
1378  case MAP_TYPE:
1380  break;
1381  case CODE_TYPE:
1382  reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1383  break;
1386  break;
1387  case HEAP_NUMBER_TYPE:
1388  case FILLER_TYPE:
1389  case BYTE_ARRAY_TYPE:
1390  case FREE_SPACE_TYPE:
1400  break;
1402  SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this);
1403  shared->SharedFunctionInfoIterateBody(v);
1404  break;
1405  }
1406 
1407 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1408  case NAME##_TYPE:
1410 #undef MAKE_STRUCT_CASE
1411  StructBodyDescriptor::IterateBody(this, object_size, v);
1412  break;
1413  default:
1414  PrintF("Unknown type: %d\n", type);
1415  UNREACHABLE();
1416  }
1417 }
1418 
1419 
1421  // NaN, +0, and -0 should return the false object
1422 #if __BYTE_ORDER == __LITTLE_ENDIAN
1424 #elif __BYTE_ORDER == __BIG_ENDIAN
1426 #endif
1427  u.d = value();
1428  if (u.bits.exp == 2047) {
1429  // Detect NaN for IEEE double precision floating point.
1430  if ((u.bits.man_low | u.bits.man_high) != 0)
1431  return GetHeap()->false_value();
1432  }
1433  if (u.bits.exp == 0) {
1434  // Detect +0, and -0 for IEEE double precision floating point.
1435  if ((u.bits.man_low | u.bits.man_high) == 0)
1436  return GetHeap()->false_value();
1437  }
1438  return GetHeap()->true_value();
1439 }
1440 
1441 
1443  PrintF(out, "%.16g", Number());
1444 }
1445 
1446 
1448  // The Windows version of vsnprintf can allocate when printing a %g string
1449  // into a buffer that may not be big enough. We don't want random memory
1450  // allocation when producing post-crash stack traces, so we print into a
1451  // buffer that is plenty big enough for any floating point number, then
1452  // print that using vsnprintf (which may truncate but never allocate if
1453  // there is no more space in the buffer).
1455  OS::SNPrintF(buffer, "%.16g", Number());
1456  accumulator->Add("%s", buffer.start());
1457 }
1458 
1459 
1461  if (IsJSFunction() && IsJSFunctionProxy()) {
1462  return GetHeap()->function_class_symbol();
1463  }
1464  if (map()->constructor()->IsJSFunction()) {
1465  JSFunction* constructor = JSFunction::cast(map()->constructor());
1466  return String::cast(constructor->shared()->instance_class_name());
1467  }
1468  // If the constructor is not present, return "Object".
1469  return GetHeap()->Object_symbol();
1470 }
1471 
1472 
1474  if (map()->constructor()->IsJSFunction()) {
1475  JSFunction* constructor = JSFunction::cast(map()->constructor());
1476  String* name = String::cast(constructor->shared()->name());
1477  if (name->length() > 0) return name;
1478  String* inferred_name = constructor->shared()->inferred_name();
1479  if (inferred_name->length() > 0) return inferred_name;
1480  Object* proto = GetPrototype();
1481  if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1482  }
1483  // TODO(rossberg): what about proxies?
1484  // If the constructor is not present, return "Object".
1485  return GetHeap()->Object_symbol();
1486 }
1487 
1488 
1490  String* name,
1491  Object* value) {
1492  int index = new_map->PropertyIndexFor(name);
1493  if (map()->unused_property_fields() == 0) {
1494  ASSERT(map()->unused_property_fields() == 0);
1495  int new_unused = new_map->unused_property_fields();
1496  Object* values;
1497  { MaybeObject* maybe_values =
1498  properties()->CopySize(properties()->length() + new_unused + 1);
1499  if (!maybe_values->ToObject(&values)) return maybe_values;
1500  }
1501  set_properties(FixedArray::cast(values));
1502  }
1503  set_map(new_map);
1504  return FastPropertyAtPut(index, value);
1505 }
1506 
1507 
1508 static bool IsIdentifier(UnicodeCache* cache,
1509  unibrow::CharacterStream* buffer) {
1510  // Checks whether the buffer contains an identifier (no escape).
1511  if (!buffer->has_more()) return false;
1512  if (!cache->IsIdentifierStart(buffer->GetNext())) {
1513  return false;
1514  }
1515  while (buffer->has_more()) {
1516  if (!cache->IsIdentifierPart(buffer->GetNext())) {
1517  return false;
1518  }
1519  }
1520  return true;
1521 }
1522 
1523 
1525  Object* value,
1526  PropertyAttributes attributes,
1527  StoreFromKeyed store_mode) {
1528  ASSERT(!IsJSGlobalProxy());
1529 
1530  // Normalize the object if the name is an actual string (not the
1531  // hidden symbols) and is not a real identifier.
1532  Isolate* isolate = GetHeap()->isolate();
1533  StringInputBuffer buffer(name);
1534  if (!IsIdentifier(isolate->unicode_cache(), &buffer)
1535  && name != isolate->heap()->hidden_symbol()) {
1536  Object* obj;
1537  { MaybeObject* maybe_obj =
1539  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1540  }
1541  return AddSlowProperty(name, value, attributes);
1542  }
1543 
1544  DescriptorArray* old_descriptors = map()->instance_descriptors();
1545  // Compute the new index for new field.
1546  int index = map()->NextFreePropertyIndex();
1547 
1548  // Allocate new instance descriptors with (name, index) added
1549  FieldDescriptor new_field(name, index, attributes);
1550  Object* new_descriptors;
1551  { MaybeObject* maybe_new_descriptors =
1552  old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS);
1553  if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1554  return maybe_new_descriptors;
1555  }
1556  }
1557 
1558  // Only allow map transition if the object isn't the global object and there
1559  // is not a transition for the name, or there's a transition for the name but
1560  // it's unrelated to properties.
1561  int descriptor_index = old_descriptors->Search(name);
1562 
1563  // Element transitions are stored in the descriptor for property "", which is
1564  // not a identifier and should have forced a switch to slow properties above.
1565  bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound;
1566  bool allow_map_transition =
1567  can_insert_transition &&
1568  (isolate->context()->global_context()->object_function()->map() != map());
1569 
1570  ASSERT(index < map()->inobject_properties() ||
1571  (index - map()->inobject_properties()) < properties()->length() ||
1572  map()->unused_property_fields() == 0);
1573  // Allocate a new map for the object.
1574  Object* r;
1575  { MaybeObject* maybe_r = map()->CopyDropDescriptors();
1576  if (!maybe_r->ToObject(&r)) return maybe_r;
1577  }
1578  Map* new_map = Map::cast(r);
1579  if (allow_map_transition) {
1580  // Allocate new instance descriptors for the old map with map transition.
1581  MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
1582  Object* r;
1583  { MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS);
1584  if (!maybe_r->ToObject(&r)) return maybe_r;
1585  }
1586  old_descriptors = DescriptorArray::cast(r);
1587  }
1588 
1589  if (map()->unused_property_fields() == 0) {
1590  if (TooManyFastProperties(properties()->length(), store_mode)) {
1591  Object* obj;
1592  { MaybeObject* maybe_obj =
1594  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1595  }
1596  return AddSlowProperty(name, value, attributes);
1597  }
1598  // Make room for the new value
1599  Object* values;
1600  { MaybeObject* maybe_values =
1601  properties()->CopySize(properties()->length() + kFieldsAdded);
1602  if (!maybe_values->ToObject(&values)) return maybe_values;
1603  }
1604  set_properties(FixedArray::cast(values));
1606  } else {
1607  new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
1608  }
1609  // We have now allocated all the necessary objects.
1610  // All the changes can be applied at once, so they are atomic.
1611  if (allow_map_transition) {
1612  map()->set_instance_descriptors(old_descriptors);
1613  }
1614  new_map->SetBackPointer(map());
1615  new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1616  set_map(new_map);
1617  return FastPropertyAtPut(index, value);
1618 }
1619 
1620 
1622  String* name,
1623  JSFunction* function,
1624  PropertyAttributes attributes) {
1625  // Allocate new instance descriptors with (name, function) added
1626  ConstantFunctionDescriptor d(name, function, attributes);
1627  Object* new_descriptors;
1628  { MaybeObject* maybe_new_descriptors =
1629  map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS);
1630  if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1631  return maybe_new_descriptors;
1632  }
1633  }
1634 
1635  // Allocate a new map for the object.
1636  Object* new_map;
1637  { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
1638  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1639  }
1640 
1641  DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
1642  Map::cast(new_map)->set_instance_descriptors(descriptors);
1643  Map* old_map = map();
1644  set_map(Map::cast(new_map));
1645 
1646  // If the old map is the global object map (from new Object()),
1647  // then transitions are not added to it, so we are done.
1648  Heap* heap = GetHeap();
1649  if (old_map == heap->isolate()->context()->global_context()->
1650  object_function()->map()) {
1651  return function;
1652  }
1653 
1654  // Do not add CONSTANT_TRANSITIONS to global objects
1655  if (IsGlobalObject()) {
1656  return function;
1657  }
1658 
1659  // Add a CONSTANT_TRANSITION descriptor to the old map,
1660  // so future assignments to this property on other objects
1661  // of the same type will create a normal field, not a constant function.
1662  // Don't do this for special properties, with non-trival attributes.
1663  if (attributes != NONE) {
1664  return function;
1665  }
1666  ConstTransitionDescriptor mark(name, Map::cast(new_map));
1667  { MaybeObject* maybe_new_descriptors =
1668  old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS);
1669  if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1670  // We have accomplished the main goal, so return success.
1671  return function;
1672  }
1673  }
1674  old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1675  Map::cast(new_map)->SetBackPointer(old_map);
1676 
1677  return function;
1678 }
1679 
1680 
1681 // Add property in slow mode
1683  Object* value,
1684  PropertyAttributes attributes) {
1687  Object* store_value = value;
1688  if (IsGlobalObject()) {
1689  // In case name is an orphaned property reuse the cell.
1690  int entry = dict->FindEntry(name);
1691  if (entry != StringDictionary::kNotFound) {
1692  store_value = dict->ValueAt(entry);
1693  JSGlobalPropertyCell::cast(store_value)->set_value(value);
1694  // Assign an enumeration index to the property and update
1695  // SetNextEnumerationIndex.
1696  int index = dict->NextEnumerationIndex();
1697  PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
1698  dict->SetNextEnumerationIndex(index + 1);
1699  dict->SetEntry(entry, name, store_value, details);
1700  return value;
1701  }
1702  Heap* heap = GetHeap();
1703  { MaybeObject* maybe_store_value =
1704  heap->AllocateJSGlobalPropertyCell(value);
1705  if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
1706  }
1707  JSGlobalPropertyCell::cast(store_value)->set_value(value);
1708  }
1709  PropertyDetails details = PropertyDetails(attributes, NORMAL);
1710  Object* result;
1711  { MaybeObject* maybe_result = dict->Add(name, store_value, details);
1712  if (!maybe_result->ToObject(&result)) return maybe_result;
1713  }
1714  if (dict != result) set_properties(StringDictionary::cast(result));
1715  return value;
1716 }
1717 
1718 
1720  Object* value,
1721  PropertyAttributes attributes,
1722  StrictModeFlag strict_mode,
1723  JSReceiver::StoreFromKeyed store_mode) {
1724  ASSERT(!IsJSGlobalProxy());
1725  Map* map_of_this = map();
1726  Heap* heap = GetHeap();
1727  if (!map_of_this->is_extensible()) {
1728  if (strict_mode == kNonStrictMode) {
1729  return value;
1730  } else {
1731  Handle<Object> args[1] = {Handle<String>(name)};
1732  return heap->isolate()->Throw(
1733  *FACTORY->NewTypeError("object_not_extensible",
1734  HandleVector(args, 1)));
1735  }
1736  }
1737  if (HasFastProperties()) {
1738  // Ensure the descriptor array does not get too big.
1739  if (map_of_this->instance_descriptors()->number_of_descriptors() <
1741  if (value->IsJSFunction()) {
1742  return AddConstantFunctionProperty(name,
1743  JSFunction::cast(value),
1744  attributes);
1745  } else {
1746  return AddFastProperty(name, value, attributes, store_mode);
1747  }
1748  } else {
1749  // Normalize the object to prevent very large instance descriptors.
1750  // This eliminates unwanted N^2 allocation and lookup behavior.
1751  Object* obj;
1752  { MaybeObject* maybe_obj =
1754  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1755  }
1756  }
1757  }
1758  return AddSlowProperty(name, value, attributes);
1759 }
1760 
1761 
1763  String* name,
1764  Object* value,
1765  PropertyAttributes attributes,
1766  StrictModeFlag strict_mode) {
1767  // Check local property, ignore interceptor.
1768  LookupResult result(GetIsolate());
1769  LocalLookupRealNamedProperty(name, &result);
1770  if (result.IsFound()) {
1771  // An existing property, a map transition or a null descriptor was
1772  // found. Use set property to handle all these cases.
1773  return SetProperty(&result, name, value, attributes, strict_mode);
1774  }
1775  bool done = false;
1776  MaybeObject* result_object;
1777  result_object =
1778  SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done);
1779  if (done) return result_object;
1780  // Add a new real property.
1781  return AddProperty(name, value, attributes, strict_mode);
1782 }
1783 
1784 
1786  Object* value,
1787  PropertyAttributes attributes) {
1788  StringDictionary* dictionary = property_dictionary();
1789  int old_index = dictionary->FindEntry(name);
1790  int new_enumeration_index = 0; // 0 means "Use the next available index."
1791  if (old_index != -1) {
1792  // All calls to ReplaceSlowProperty have had all transitions removed.
1793  ASSERT(!dictionary->ContainsTransition(old_index));
1794  new_enumeration_index = dictionary->DetailsAt(old_index).index();
1795  }
1796 
1797  PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
1798  return SetNormalizedProperty(name, value, new_details);
1799 }
1800 
1801 
1803  String* name,
1804  Object* new_value,
1805  PropertyAttributes attributes) {
1806  Map* old_map = map();
1807  Object* result;
1808  { MaybeObject* maybe_result =
1809  ConvertDescriptorToField(name, new_value, attributes);
1810  if (!maybe_result->ToObject(&result)) return maybe_result;
1811  }
1812  // If we get to this point we have succeeded - do not return failure
1813  // after this point. Later stuff is optional.
1814  if (!HasFastProperties()) {
1815  return result;
1816  }
1817  // Do not add transitions to the map of "new Object()".
1818  if (map() == GetIsolate()->context()->global_context()->
1819  object_function()->map()) {
1820  return result;
1821  }
1822 
1823  MapTransitionDescriptor transition(name,
1824  map(),
1825  attributes);
1826  Object* new_descriptors;
1827  { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()->
1828  CopyInsert(&transition, KEEP_TRANSITIONS);
1829  if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1830  return result; // Yes, return _result_.
1831  }
1832  }
1833  old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1834  map()->SetBackPointer(old_map);
1835  return result;
1836 }
1837 
1838 
1840  Object* new_value,
1841  PropertyAttributes attributes) {
1842  if (map()->unused_property_fields() == 0 &&
1843  TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) {
1844  Object* obj;
1845  { MaybeObject* maybe_obj =
1847  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1848  }
1849  return ReplaceSlowProperty(name, new_value, attributes);
1850  }
1851 
1852  int index = map()->NextFreePropertyIndex();
1853  FieldDescriptor new_field(name, index, attributes);
1854  // Make a new DescriptorArray replacing an entry with FieldDescriptor.
1855  Object* descriptors_unchecked;
1856  { MaybeObject* maybe_descriptors_unchecked = map()->instance_descriptors()->
1857  CopyInsert(&new_field, REMOVE_TRANSITIONS);
1858  if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
1859  return maybe_descriptors_unchecked;
1860  }
1861  }
1862  DescriptorArray* new_descriptors =
1863  DescriptorArray::cast(descriptors_unchecked);
1864 
1865  // Make a new map for the object.
1866  Object* new_map_unchecked;
1867  { MaybeObject* maybe_new_map_unchecked = map()->CopyDropDescriptors();
1868  if (!maybe_new_map_unchecked->ToObject(&new_map_unchecked)) {
1869  return maybe_new_map_unchecked;
1870  }
1871  }
1872  Map* new_map = Map::cast(new_map_unchecked);
1873  new_map->set_instance_descriptors(new_descriptors);
1874 
1875  // Make new properties array if necessary.
1876  FixedArray* new_properties = 0; // Will always be NULL or a valid pointer.
1877  int new_unused_property_fields = map()->unused_property_fields() - 1;
1878  if (map()->unused_property_fields() == 0) {
1879  new_unused_property_fields = kFieldsAdded - 1;
1880  Object* new_properties_object;
1881  { MaybeObject* maybe_new_properties_object =
1882  properties()->CopySize(properties()->length() + kFieldsAdded);
1883  if (!maybe_new_properties_object->ToObject(&new_properties_object)) {
1884  return maybe_new_properties_object;
1885  }
1886  }
1887  new_properties = FixedArray::cast(new_properties_object);
1888  }
1889 
1890  // Update pointers to commit changes.
1891  // Object points to the new map.
1892  new_map->set_unused_property_fields(new_unused_property_fields);
1893  set_map(new_map);
1894  if (new_properties) {
1895  set_properties(FixedArray::cast(new_properties));
1896  }
1897  return FastPropertyAtPut(index, new_value);
1898 }
1899 
1900 
1901 
1903  String* name,
1904  Object* value,
1905  PropertyAttributes attributes,
1906  StrictModeFlag strict_mode) {
1907  Isolate* isolate = GetIsolate();
1908  HandleScope scope(isolate);
1909  Handle<JSObject> this_handle(this);
1910  Handle<String> name_handle(name);
1911  Handle<Object> value_handle(value, isolate);
1913  if (!interceptor->setter()->IsUndefined()) {
1914  LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name));
1915  CustomArguments args(isolate, interceptor->data(), this, this);
1916  v8::AccessorInfo info(args.end());
1917  v8::NamedPropertySetter setter =
1918  v8::ToCData<v8::NamedPropertySetter>(interceptor->setter());
1919  v8::Handle<v8::Value> result;
1920  {
1921  // Leaving JavaScript.
1922  VMState state(isolate, EXTERNAL);
1923  Handle<Object> value_unhole(value->IsTheHole() ?
1924  isolate->heap()->undefined_value() :
1925  value,
1926  isolate);
1927  result = setter(v8::Utils::ToLocal(name_handle),
1928  v8::Utils::ToLocal(value_unhole),
1929  info);
1930  }
1932  if (!result.IsEmpty()) return *value_handle;
1933  }
1934  MaybeObject* raw_result =
1935  this_handle->SetPropertyPostInterceptor(*name_handle,
1936  *value_handle,
1937  attributes,
1938  strict_mode);
1940  return raw_result;
1941 }
1942 
1943 
1945  Handle<String> key,
1946  Handle<Object> value,
1947  PropertyAttributes attributes,
1948  StrictModeFlag strict_mode) {
1949  CALL_HEAP_FUNCTION(object->GetIsolate(),
1950  object->SetProperty(*key, *value, attributes, strict_mode),
1951  Object);
1952 }
1953 
1954 
1955 MaybeObject* JSReceiver::SetProperty(String* name,
1956  Object* value,
1957  PropertyAttributes attributes,
1958  StrictModeFlag strict_mode,
1959  JSReceiver::StoreFromKeyed store_mode) {
1960  LookupResult result(GetIsolate());
1961  LocalLookup(name, &result);
1962  return SetProperty(&result, name, value, attributes, strict_mode, store_mode);
1963 }
1964 
1965 
1967  String* name,
1968  Object* value,
1969  JSObject* holder,
1970  StrictModeFlag strict_mode) {
1971  Isolate* isolate = GetIsolate();
1972  HandleScope scope(isolate);
1973 
1974  // We should never get here to initialize a const with the hole
1975  // value since a const declaration would conflict with the setter.
1976  ASSERT(!value->IsTheHole());
1977  Handle<Object> value_handle(value, isolate);
1978 
1979  // To accommodate both the old and the new api we switch on the
1980  // data structure used to store the callbacks. Eventually foreign
1981  // callbacks should be phased out.
1982  if (structure->IsForeign()) {
1983  AccessorDescriptor* callback =
1984  reinterpret_cast<AccessorDescriptor*>(
1985  Foreign::cast(structure)->foreign_address());
1986  MaybeObject* obj = (callback->setter)(this, value, callback->data);
1988  if (obj->IsFailure()) return obj;
1989  return *value_handle;
1990  }
1991 
1992  if (structure->IsAccessorInfo()) {
1993  // api style callbacks
1994  AccessorInfo* data = AccessorInfo::cast(structure);
1995  if (!data->IsCompatibleReceiver(this)) {
1996  Handle<Object> name_handle(name);
1997  Handle<Object> receiver_handle(this);
1998  Handle<Object> args[2] = { name_handle, receiver_handle };
1999  Handle<Object> error =
2000  isolate->factory()->NewTypeError("incompatible_method_receiver",
2001  HandleVector(args,
2002  ARRAY_SIZE(args)));
2003  return isolate->Throw(*error);
2004  }
2005  Object* call_obj = data->setter();
2006  v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
2007  if (call_fun == NULL) return value;
2008  Handle<String> key(name);
2009  LOG(isolate, ApiNamedPropertyAccess("store", this, name));
2010  CustomArguments args(isolate, data->data(), this, JSObject::cast(holder));
2011  v8::AccessorInfo info(args.end());
2012  {
2013  // Leaving JavaScript.
2014  VMState state(isolate, EXTERNAL);
2015  call_fun(v8::Utils::ToLocal(key),
2016  v8::Utils::ToLocal(value_handle),
2017  info);
2018  }
2020  return *value_handle;
2021  }
2022 
2023  if (structure->IsAccessorPair()) {
2024  Object* setter = AccessorPair::cast(structure)->setter();
2025  if (setter->IsSpecFunction()) {
2026  // TODO(rossberg): nicer would be to cast to some JSCallable here...
2027  return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
2028  } else {
2029  if (strict_mode == kNonStrictMode) {
2030  return value;
2031  }
2032  Handle<String> key(name);
2033  Handle<Object> holder_handle(holder, isolate);
2034  Handle<Object> args[2] = { key, holder_handle };
2035  return isolate->Throw(
2036  *isolate->factory()->NewTypeError("no_setter_in_callback",
2037  HandleVector(args, 2)));
2038  }
2039  }
2040 
2041  UNREACHABLE();
2042  return NULL;
2043 }
2044 
2045 
2047  Object* value) {
2048  Isolate* isolate = GetIsolate();
2049  Handle<Object> value_handle(value, isolate);
2050  Handle<JSReceiver> fun(setter, isolate);
2051  Handle<JSReceiver> self(this, isolate);
2052 #ifdef ENABLE_DEBUGGER_SUPPORT
2053  Debug* debug = isolate->debug();
2054  // Handle stepping into a setter if step into is active.
2055  // TODO(rossberg): should this apply to getters that are function proxies?
2056  if (debug->StepInActive() && fun->IsJSFunction()) {
2057  debug->HandleStepIn(
2059  }
2060 #endif
2061  bool has_pending_exception;
2062  Handle<Object> argv[] = { value_handle };
2063  Execution::Call(fun, self, ARRAY_SIZE(argv), argv, &has_pending_exception);
2064  // Check for pending exception and return the result.
2065  if (has_pending_exception) return Failure::Exception();
2066  return *value_handle;
2067 }
2068 
2069 
2071  uint32_t index,
2072  Object* value,
2073  bool* found,
2074  StrictModeFlag strict_mode) {
2075  Heap* heap = GetHeap();
2076  for (Object* pt = GetPrototype();
2077  pt != heap->null_value();
2078  pt = pt->GetPrototype()) {
2079  if (pt->IsJSProxy()) {
2080  String* name;
2081  MaybeObject* maybe = GetHeap()->Uint32ToString(index);
2082  if (!maybe->To<String>(&name)) {
2083  *found = true; // Force abort
2084  return maybe;
2085  }
2087  this, name, value, NONE, strict_mode, found);
2088  }
2089  if (!JSObject::cast(pt)->HasDictionaryElements()) {
2090  continue;
2091  }
2092  SeededNumberDictionary* dictionary =
2094  int entry = dictionary->FindEntry(index);
2095  if (entry != SeededNumberDictionary::kNotFound) {
2096  PropertyDetails details = dictionary->DetailsAt(entry);
2097  if (details.type() == CALLBACKS) {
2098  *found = true;
2099  return SetElementWithCallback(dictionary->ValueAt(entry),
2100  index,
2101  value,
2102  JSObject::cast(pt),
2103  strict_mode);
2104  }
2105  }
2106  }
2107  *found = false;
2108  return heap->the_hole_value();
2109 }
2110 
2111 MaybeObject* JSObject::SetPropertyViaPrototypes(
2112  String* name,
2113  Object* value,
2114  PropertyAttributes attributes,
2115  StrictModeFlag strict_mode,
2116  bool* done) {
2117  Heap* heap = GetHeap();
2118  Isolate* isolate = heap->isolate();
2119 
2120  *done = false;
2121  // We could not find a local property so let's check whether there is an
2122  // accessor that wants to handle the property, or whether the property is
2123  // read-only on the prototype chain.
2124  LookupResult result(isolate);
2125  LookupRealNamedPropertyInPrototypes(name, &result);
2126  if (result.IsFound()) {
2127  switch (result.type()) {
2128  case NORMAL:
2129  case FIELD:
2130  case CONSTANT_FUNCTION:
2131  *done = result.IsReadOnly();
2132  break;
2133  case INTERCEPTOR: {
2134  PropertyAttributes attr =
2135  result.holder()->GetPropertyAttributeWithInterceptor(
2136  this, name, true);
2137  *done = !!(attr & READ_ONLY);
2138  break;
2139  }
2140  case CALLBACKS: {
2141  if (!FLAG_es5_readonly && result.IsReadOnly()) break;
2142  *done = true;
2143  return SetPropertyWithCallback(result.GetCallbackObject(),
2144  name, value, result.holder(), strict_mode);
2145  }
2146  case HANDLER: {
2147  return result.proxy()->SetPropertyViaPrototypesWithHandler(
2148  this, name, value, attributes, strict_mode, done);
2149  }
2150  case MAP_TRANSITION:
2151  case CONSTANT_TRANSITION:
2152  case NULL_DESCRIPTOR:
2153  break;
2154  }
2155  }
2156 
2157  // If we get here with *done true, we have encountered a read-only property.
2158  if (!FLAG_es5_readonly) *done = false;
2159  if (*done) {
2160  if (strict_mode == kNonStrictMode) return value;
2161  Handle<Object> args[] = { Handle<Object>(name), Handle<Object>(this)};
2162  return isolate->Throw(*isolate->factory()->NewTypeError(
2163  "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2164  }
2165  return heap->the_hole_value();
2166 }
2167 
2168 
2169 void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
2170  DescriptorArray* descriptors = map()->instance_descriptors();
2171  int number = descriptors->SearchWithCache(name);
2172  if (number != DescriptorArray::kNotFound) {
2173  result->DescriptorResult(this, descriptors->GetDetails(number), number);
2174  } else {
2175  result->NotFound();
2176  }
2177 }
2178 
2179 
2181  String* name,
2182  LookupResult* result) {
2183  DescriptorArray* descriptors = instance_descriptors();
2184  DescriptorLookupCache* cache =
2186  int number = cache->Lookup(descriptors, name);
2187  if (number == DescriptorLookupCache::kAbsent) {
2188  number = descriptors->Search(name);
2189  cache->Update(descriptors, name, number);
2190  }
2191  if (number != DescriptorArray::kNotFound) {
2192  result->DescriptorResult(holder, descriptors->GetDetails(number), number);
2193  } else {
2194  result->NotFound();
2195  }
2196 }
2197 
2198 
2199 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
2200  ASSERT(!map.is_null());
2201  for (int i = 0; i < maps->length(); ++i) {
2202  if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
2203  }
2204  return false;
2205 }
2206 
2207 
2208 template <class T>
2209 static Handle<T> MaybeNull(T* p) {
2210  if (p == NULL) return Handle<T>::null();
2211  return Handle<T>(p);
2212 }
2213 
2214 
2216  ElementsKind kind = elements_kind();
2217  Handle<Map> transitioned_map = Handle<Map>::null();
2218  Handle<Map> current_map(this);
2219  bool packed = IsFastPackedElementsKind(kind);
2221  while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
2222  kind = GetNextMoreGeneralFastElementsKind(kind, false);
2223  Handle<Map> maybe_transitioned_map =
2224  MaybeNull(current_map->LookupElementsTransitionMap(kind));
2225  if (maybe_transitioned_map.is_null()) break;
2226  if (ContainsMap(candidates, maybe_transitioned_map) &&
2227  (packed || !IsFastPackedElementsKind(kind))) {
2228  transitioned_map = maybe_transitioned_map;
2229  if (!IsFastPackedElementsKind(kind)) packed = false;
2230  }
2231  current_map = maybe_transitioned_map;
2232  }
2233  }
2234  return transitioned_map;
2235 }
2236 
2237 
2238 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
2239  Map* current_map = map;
2241  int to_index = GetSequenceIndexFromFastElementsKind(to_kind);
2242  for (; index < to_index; ++index) {
2243  Map* next_map = current_map->elements_transition_map();
2244  if (next_map == NULL) {
2245  return current_map;
2246  }
2247  current_map = next_map;
2248  }
2249  ASSERT(current_map->elements_kind() == to_kind);
2250  return current_map;
2251 }
2252 
2253 
2255  if (this->instance_descriptors()->MayContainTransitions() &&
2256  IsMoreGeneralElementsKindTransition(this->elements_kind(), to_kind)) {
2257  Map* to_map = FindClosestElementsTransition(this, to_kind);
2258  if (to_map->elements_kind() == to_kind) {
2259  return to_map;
2260  }
2261  }
2262  return NULL;
2263 }
2264 
2265 
2267  ASSERT(elements_transition_map() == NULL);
2268  ASSERT(GetSequenceIndexFromFastElementsKind(elements_kind()) ==
2269  (GetSequenceIndexFromFastElementsKind(next_kind) - 1));
2270 
2271  Map* next_map;
2272  MaybeObject* maybe_next_map =
2273  this->CopyDropTransitions(DescriptorArray::CANNOT_BE_SHARED);
2274  if (!maybe_next_map->To(&next_map)) return maybe_next_map;
2275 
2276  next_map->set_elements_kind(next_kind);
2277  next_map->SetBackPointer(this);
2278  this->set_elements_transition_map(next_map);
2279  return next_map;
2280 }
2281 
2282 
2283 static MaybeObject* AddMissingElementsTransitions(Map* map,
2284  ElementsKind to_kind) {
2285  int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()) + 1;
2286  int to_index = GetSequenceIndexFromFastElementsKind(to_kind);
2287  ASSERT(index <= to_index);
2288 
2289  Map* current_map = map;
2290 
2291  for (; index <= to_index; ++index) {
2293  MaybeObject* maybe_next_map =
2294  current_map->CreateNextElementsTransition(next_kind);
2295  if (!maybe_next_map->To(&current_map)) return maybe_next_map;
2296  }
2297 
2298  ASSERT(current_map->elements_kind() == to_kind);
2299  return current_map;
2300 }
2301 
2302 
2304  ElementsKind to_kind) {
2305  Isolate* isolate = object->GetIsolate();
2306  CALL_HEAP_FUNCTION(isolate,
2307  object->GetElementsTransitionMap(isolate, to_kind),
2308  Map);
2309 }
2310 
2311 
2312 // If the map is using the empty descriptor array, install a new empty
2313 // descriptor array that will contain an element transition.
2314 // TODO(verwaest) Goes away once the descriptor array is immutable.
2315 static MaybeObject* EnsureMayContainTransitions(Map* map) {
2316  if (map->instance_descriptors()->MayContainTransitions()) return map;
2317  DescriptorArray* descriptor_array;
2318  MaybeObject* maybe_descriptor_array =
2320  if (!maybe_descriptor_array->To(&descriptor_array)) {
2321  return maybe_descriptor_array;
2322  }
2323  map->set_instance_descriptors(descriptor_array);
2324  return map;
2325 }
2326 
2327 
2329  Map* start_map = map();
2330  ElementsKind from_kind = start_map->elements_kind();
2331 
2332  if (from_kind == to_kind) {
2333  return start_map;
2334  }
2335 
2336  Context* global_context = GetIsolate()->context()->global_context();
2337  bool allow_store_transition =
2338  // Only remember the map transition if the object's map is NOT equal to
2339  // the global object_function's map and there is not an already existing
2340  // non-matching element transition.
2341  (global_context->object_function()->map() != map()) &&
2342  !start_map->IsUndefined() && !start_map->is_shared() &&
2343  // Only store fast element maps in ascending generality.
2344  IsTransitionableFastElementsKind(from_kind) &&
2345  IsFastElementsKind(to_kind) &&
2346  IsMoreGeneralElementsKindTransition(from_kind, to_kind);
2347 
2348  if (!allow_store_transition) {
2349  // Create a new free-floating map only if we are not allowed to store it.
2350  Map* new_map = NULL;
2351  MaybeObject* maybe_new_map =
2353  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2354  new_map->set_elements_kind(to_kind);
2355  return new_map;
2356  }
2357 
2358  EnsureMayContainTransitions(start_map);
2359  Map* closest_map = FindClosestElementsTransition(start_map, to_kind);
2360 
2361  if (closest_map->elements_kind() == to_kind) {
2362  return closest_map;
2363  }
2364 
2365  return AddMissingElementsTransitions(closest_map, to_kind);
2366 }
2367 
2368 
2370  LookupResult* result) {
2371  if (IsJSGlobalProxy()) {
2372  Object* proto = GetPrototype();
2373  if (proto->IsNull()) return result->NotFound();
2374  ASSERT(proto->IsJSGlobalObject());
2375  // A GlobalProxy's prototype should always be a proper JSObject.
2376  return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
2377  }
2378 
2379  if (HasFastProperties()) {
2380  LookupInDescriptor(name, result);
2381  if (result->IsFound()) {
2382  // A property, a map transition or a null descriptor was found.
2383  // We return all of these result types because
2384  // LocalLookupRealNamedProperty is used when setting properties
2385  // where map transitions and null descriptors are handled.
2386  ASSERT(result->holder() == this && result->type() != NORMAL);
2387  // Disallow caching for uninitialized constants. These can only
2388  // occur as fields.
2389  if (result->IsReadOnly() && result->type() == FIELD &&
2390  FastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
2391  result->DisallowCaching();
2392  }
2393  return;
2394  }
2395  } else {
2396  int entry = property_dictionary()->FindEntry(name);
2397  if (entry != StringDictionary::kNotFound) {
2398  Object* value = property_dictionary()->ValueAt(entry);
2399  if (IsGlobalObject()) {
2400  PropertyDetails d = property_dictionary()->DetailsAt(entry);
2401  if (d.IsDeleted()) {
2402  result->NotFound();
2403  return;
2404  }
2405  value = JSGlobalPropertyCell::cast(value)->value();
2406  }
2407  // Make sure to disallow caching for uninitialized constants
2408  // found in the dictionary-mode objects.
2409  if (value->IsTheHole()) result->DisallowCaching();
2410  result->DictionaryResult(this, entry);
2411  return;
2412  }
2413  }
2414  result->NotFound();
2415 }
2416 
2417 
2418 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
2419  LocalLookupRealNamedProperty(name, result);
2420  if (result->IsProperty()) return;
2421 
2423 }
2424 
2425 
2427  LookupResult* result) {
2428  Heap* heap = GetHeap();
2429  for (Object* pt = GetPrototype();
2430  pt != heap->null_value();
2431  pt = pt->GetPrototype()) {
2432  if (pt->IsJSProxy()) {
2433  return result->HandlerResult(JSProxy::cast(pt));
2434  }
2435  JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
2436  ASSERT(!(result->IsProperty() && result->type() == INTERCEPTOR));
2437  if (result->IsProperty()) return;
2438  }
2439  result->NotFound();
2440 }
2441 
2442 
2443 // We only need to deal with CALLBACKS and INTERCEPTORS
2445  LookupResult* result,
2446  String* name,
2447  Object* value,
2448  bool check_prototype,
2449  StrictModeFlag strict_mode) {
2450  if (check_prototype && !result->IsProperty()) {
2452  }
2453 
2454  if (result->IsProperty()) {
2455  if (!result->IsReadOnly()) {
2456  switch (result->type()) {
2457  case CALLBACKS: {
2458  Object* obj = result->GetCallbackObject();
2459  if (obj->IsAccessorInfo()) {
2460  AccessorInfo* info = AccessorInfo::cast(obj);
2461  if (info->all_can_write()) {
2462  return SetPropertyWithCallback(result->GetCallbackObject(),
2463  name,
2464  value,
2465  result->holder(),
2466  strict_mode);
2467  }
2468  }
2469  break;
2470  }
2471  case INTERCEPTOR: {
2472  // Try lookup real named properties. Note that only property can be
2473  // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
2474  LookupResult r(GetIsolate());
2475  LookupRealNamedProperty(name, &r);
2476  if (r.IsProperty()) {
2478  name,
2479  value,
2480  check_prototype,
2481  strict_mode);
2482  }
2483  break;
2484  }
2485  default: {
2486  break;
2487  }
2488  }
2489  }
2490  }
2491 
2492  Isolate* isolate = GetIsolate();
2493  HandleScope scope(isolate);
2494  Handle<Object> value_handle(value);
2495  isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
2496  return *value_handle;
2497 }
2498 
2499 
2500 MaybeObject* JSReceiver::SetProperty(LookupResult* result,
2501  String* key,
2502  Object* value,
2503  PropertyAttributes attributes,
2504  StrictModeFlag strict_mode,
2505  JSReceiver::StoreFromKeyed store_mode) {
2506  if (result->IsFound() && result->type() == HANDLER) {
2507  return result->proxy()->SetPropertyWithHandler(
2508  this, key, value, attributes, strict_mode);
2509  } else {
2510  return JSObject::cast(this)->SetPropertyForResult(
2511  result, key, value, attributes, strict_mode, store_mode);
2512  }
2513 }
2514 
2515 
2517  Isolate* isolate = GetIsolate();
2518  HandleScope scope(isolate);
2519  Handle<Object> receiver(this);
2520  Handle<Object> name(name_raw);
2521 
2522  Handle<Object> args[] = { name };
2523  Handle<Object> result = CallTrap(
2524  "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
2525  if (isolate->has_pending_exception()) return false;
2526 
2527  return result->ToBoolean()->IsTrue();
2528 }
2529 
2530 
2532  JSReceiver* receiver_raw,
2533  String* name_raw,
2534  Object* value_raw,
2535  PropertyAttributes attributes,
2536  StrictModeFlag strict_mode) {
2537  Isolate* isolate = GetIsolate();
2538  HandleScope scope(isolate);
2539  Handle<JSReceiver> receiver(receiver_raw);
2540  Handle<Object> name(name_raw);
2541  Handle<Object> value(value_raw);
2542 
2543  Handle<Object> args[] = { receiver, name, value };
2544  CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
2545  if (isolate->has_pending_exception()) return Failure::Exception();
2546 
2547  return *value;
2548 }
2549 
2550 
2552  JSReceiver* receiver_raw,
2553  String* name_raw,
2554  Object* value_raw,
2555  PropertyAttributes attributes,
2556  StrictModeFlag strict_mode,
2557  bool* done) {
2558  Isolate* isolate = GetIsolate();
2559  Handle<JSProxy> proxy(this);
2560  Handle<JSReceiver> receiver(receiver_raw);
2561  Handle<String> name(name_raw);
2562  Handle<Object> value(value_raw);
2563  Handle<Object> handler(this->handler()); // Trap might morph proxy.
2564 
2565  *done = true; // except where redefined...
2566  Handle<Object> args[] = { name };
2567  Handle<Object> result = proxy->CallTrap(
2568  "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2569  if (isolate->has_pending_exception()) return Failure::Exception();
2570 
2571  if (result->IsUndefined()) {
2572  *done = false;
2573  return GetHeap()->the_hole_value();
2574  }
2575 
2576  // Emulate [[GetProperty]] semantics for proxies.
2577  bool has_pending_exception;
2578  Handle<Object> argv[] = { result };
2579  Handle<Object> desc =
2580  Execution::Call(isolate->to_complete_property_descriptor(), result,
2581  ARRAY_SIZE(argv), argv, &has_pending_exception);
2582  if (has_pending_exception) return Failure::Exception();
2583 
2584  // [[GetProperty]] requires to check that all properties are configurable.
2585  Handle<String> configurable_name =
2586  isolate->factory()->LookupAsciiSymbol("configurable_");
2587  Handle<Object> configurable(
2588  v8::internal::GetProperty(desc, configurable_name));
2589  ASSERT(!isolate->has_pending_exception());
2590  ASSERT(configurable->IsTrue() || configurable->IsFalse());
2591  if (configurable->IsFalse()) {
2592  Handle<String> trap =
2593  isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
2594  Handle<Object> args[] = { handler, trap, name };
2595  Handle<Object> error = isolate->factory()->NewTypeError(
2596  "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2597  return isolate->Throw(*error);
2598  }
2599  ASSERT(configurable->IsTrue());
2600 
2601  // Check for DataDescriptor.
2602  Handle<String> hasWritable_name =
2603  isolate->factory()->LookupAsciiSymbol("hasWritable_");
2604  Handle<Object> hasWritable(v8::internal::GetProperty(desc, hasWritable_name));
2605  ASSERT(!isolate->has_pending_exception());
2606  ASSERT(hasWritable->IsTrue() || hasWritable->IsFalse());
2607  if (hasWritable->IsTrue()) {
2608  Handle<String> writable_name =
2609  isolate->factory()->LookupAsciiSymbol("writable_");
2610  Handle<Object> writable(v8::internal::GetProperty(desc, writable_name));
2611  ASSERT(!isolate->has_pending_exception());
2612  ASSERT(writable->IsTrue() || writable->IsFalse());
2613  *done = writable->IsFalse();
2614  if (!*done) return GetHeap()->the_hole_value();
2615  if (strict_mode == kNonStrictMode) return *value;
2616  Handle<Object> args[] = { name, receiver };
2617  Handle<Object> error = isolate->factory()->NewTypeError(
2618  "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
2619  return isolate->Throw(*error);
2620  }
2621 
2622  // We have an AccessorDescriptor.
2623  Handle<String> set_name = isolate->factory()->LookupAsciiSymbol("set_");
2624  Handle<Object> setter(v8::internal::GetProperty(desc, set_name));
2625  ASSERT(!isolate->has_pending_exception());
2626  if (!setter->IsUndefined()) {
2627  // TODO(rossberg): nicer would be to cast to some JSCallable here...
2628  return receiver->SetPropertyWithDefinedSetter(
2629  JSReceiver::cast(*setter), *value);
2630  }
2631 
2632  if (strict_mode == kNonStrictMode) return *value;
2633  Handle<Object> args2[] = { name, proxy };
2634  Handle<Object> error = isolate->factory()->NewTypeError(
2635  "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2)));
2636  return isolate->Throw(*error);
2637 }
2638 
2639 
2641  String* name_raw, DeleteMode mode) {
2642  Isolate* isolate = GetIsolate();
2643  HandleScope scope(isolate);
2644  Handle<Object> receiver(this);
2645  Handle<Object> name(name_raw);
2646 
2647  Handle<Object> args[] = { name };
2648  Handle<Object> result = CallTrap(
2649  "delete", Handle<Object>(), ARRAY_SIZE(args), args);
2650  if (isolate->has_pending_exception()) return Failure::Exception();
2651 
2652  Object* bool_result = result->ToBoolean();
2653  if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
2654  Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete");
2655  Handle<Object> args[] = { Handle<Object>(handler()), trap_name };
2656  Handle<Object> error = isolate->factory()->NewTypeError(
2657  "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
2658  isolate->Throw(*error);
2659  return Failure::Exception();
2660  }
2661  return bool_result;
2662 }
2663 
2664 
2666  uint32_t index,
2667  DeleteMode mode) {
2668  Isolate* isolate = GetIsolate();
2669  HandleScope scope(isolate);
2670  Handle<String> name = isolate->factory()->Uint32ToString(index);
2671  return JSProxy::DeletePropertyWithHandler(*name, mode);
2672 }
2673 
2674 
2676  JSReceiver* receiver_raw,
2677  String* name_raw) {
2678  Isolate* isolate = GetIsolate();
2679  HandleScope scope(isolate);
2680  Handle<JSProxy> proxy(this);
2681  Handle<Object> handler(this->handler()); // Trap might morph proxy.
2682  Handle<JSReceiver> receiver(receiver_raw);
2683  Handle<Object> name(name_raw);
2684 
2685  Handle<Object> args[] = { name };
2686  Handle<Object> result = CallTrap(
2687  "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2688  if (isolate->has_pending_exception()) return NONE;
2689 
2690  if (result->IsUndefined()) return ABSENT;
2691 
2692  bool has_pending_exception;
2693  Handle<Object> argv[] = { result };
2694  Handle<Object> desc =
2695  Execution::Call(isolate->to_complete_property_descriptor(), result,
2696  ARRAY_SIZE(argv), argv, &has_pending_exception);
2697  if (has_pending_exception) return NONE;
2698 
2699  // Convert result to PropertyAttributes.
2700  Handle<String> enum_n = isolate->factory()->LookupAsciiSymbol("enumerable");
2701  Handle<Object> enumerable(v8::internal::GetProperty(desc, enum_n));
2702  if (isolate->has_pending_exception()) return NONE;
2703  Handle<String> conf_n = isolate->factory()->LookupAsciiSymbol("configurable");
2704  Handle<Object> configurable(v8::internal::GetProperty(desc, conf_n));
2705  if (isolate->has_pending_exception()) return NONE;
2706  Handle<String> writ_n = isolate->factory()->LookupAsciiSymbol("writable");
2707  Handle<Object> writable(v8::internal::GetProperty(desc, writ_n));
2708  if (isolate->has_pending_exception()) return NONE;
2709 
2710  if (configurable->IsFalse()) {
2711  Handle<String> trap =
2712  isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
2713  Handle<Object> args[] = { handler, trap, name };
2714  Handle<Object> error = isolate->factory()->NewTypeError(
2715  "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2716  isolate->Throw(*error);
2717  return NONE;
2718  }
2719 
2720  int attributes = NONE;
2721  if (enumerable->ToBoolean()->IsFalse()) attributes |= DONT_ENUM;
2722  if (configurable->ToBoolean()->IsFalse()) attributes |= DONT_DELETE;
2723  if (writable->ToBoolean()->IsFalse()) attributes |= READ_ONLY;
2724  return static_cast<PropertyAttributes>(attributes);
2725 }
2726 
2727 
2729  JSReceiver* receiver,
2730  uint32_t index) {
2731  Isolate* isolate = GetIsolate();
2732  HandleScope scope(isolate);
2733  Handle<String> name = isolate->factory()->Uint32ToString(index);
2734  return GetPropertyAttributeWithHandler(receiver, *name);
2735 }
2736 
2737 
2739  Isolate* isolate = GetIsolate();
2740  HandleScope scope(isolate);
2741  Handle<JSProxy> self(this);
2742 
2743  // Save identity hash.
2744  MaybeObject* maybe_hash = GetIdentityHash(OMIT_CREATION);
2745 
2746  if (IsJSFunctionProxy()) {
2747  isolate->factory()->BecomeJSFunction(self);
2748  // Code will be set on the JavaScript side.
2749  } else {
2750  isolate->factory()->BecomeJSObject(self);
2751  }
2752  ASSERT(self->IsJSObject());
2753 
2754  // Inherit identity, if it was present.
2755  Object* hash;
2756  if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) {
2757  Handle<JSObject> new_self(JSObject::cast(*self));
2758  isolate->factory()->SetIdentityHash(new_self, hash);
2759  }
2760 }
2761 
2762 
2764  Handle<Object> derived,
2765  int argc,
2766  Handle<Object> argv[]) {
2767  Isolate* isolate = GetIsolate();
2768  Handle<Object> handler(this->handler());
2769 
2770  Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol(name);
2771  Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2772  if (isolate->has_pending_exception()) return trap;
2773 
2774  if (trap->IsUndefined()) {
2775  if (derived.is_null()) {
2776  Handle<Object> args[] = { handler, trap_name };
2777  Handle<Object> error = isolate->factory()->NewTypeError(
2778  "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
2779  isolate->Throw(*error);
2780  return Handle<Object>();
2781  }
2782  trap = Handle<Object>(derived);
2783  }
2784 
2785  bool threw;
2786  return Execution::Call(trap, handler, argc, argv, &threw);
2787 }
2788 
2789 
2790 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
2791  String* name,
2792  Object* value,
2793  PropertyAttributes attributes,
2794  StrictModeFlag strict_mode,
2795  StoreFromKeyed store_mode) {
2796  Heap* heap = GetHeap();
2797  // Make sure that the top context does not change when doing callbacks or
2798  // interceptor calls.
2799  AssertNoContextChange ncc;
2800 
2801  // Optimization for 2-byte strings often used as keys in a decompression
2802  // dictionary. We make these short keys into symbols to avoid constantly
2803  // reallocating them.
2804  if (!name->IsSymbol() && name->length() <= 2) {
2805  Object* symbol_version;
2806  { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name);
2807  if (maybe_symbol_version->ToObject(&symbol_version)) {
2808  name = String::cast(symbol_version);
2809  }
2810  }
2811  }
2812 
2813  // Check access rights if needed.
2814  if (IsAccessCheckNeeded()) {
2815  if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
2817  result, name, value, true, strict_mode);
2818  }
2819  }
2820 
2821  if (IsJSGlobalProxy()) {
2822  Object* proto = GetPrototype();
2823  if (proto->IsNull()) return value;
2824  ASSERT(proto->IsJSGlobalObject());
2825  return JSObject::cast(proto)->SetPropertyForResult(
2826  result, name, value, attributes, strict_mode, store_mode);
2827  }
2828 
2829  if (!result->IsProperty() && !IsJSContextExtensionObject()) {
2830  bool done = false;
2831  MaybeObject* result_object =
2832  SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done);
2833  if (done) return result_object;
2834  }
2835 
2836  if (!result->IsFound()) {
2837  // Neither properties nor transitions found.
2838  return AddProperty(name, value, attributes, strict_mode, store_mode);
2839  }
2840  if (result->IsReadOnly() && result->IsProperty()) {
2841  if (strict_mode == kStrictMode) {
2842  Handle<JSObject> self(this);
2843  Handle<String> hname(name);
2844  Handle<Object> args[] = { hname, self };
2845  return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
2846  "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2847  } else {
2848  return value;
2849  }
2850  }
2851  // This is a real property that is not read-only, or it is a
2852  // transition or null descriptor and there are no setters in the prototypes.
2853  switch (result->type()) {
2854  case NORMAL:
2855  return SetNormalizedProperty(result, value);
2856  case FIELD:
2857  return FastPropertyAtPut(result->GetFieldIndex(), value);
2858  case MAP_TRANSITION:
2859  if (attributes == result->GetAttributes()) {
2860  // Only use map transition if the attributes match.
2861  return AddFastPropertyUsingMap(result->GetTransitionMap(),
2862  name,
2863  value);
2864  }
2865  return ConvertDescriptorToField(name, value, attributes);
2866  case CONSTANT_FUNCTION:
2867  // Only replace the function if necessary.
2868  if (value == result->GetConstantFunction()) return value;
2869  // Preserve the attributes of this existing property.
2870  attributes = result->GetAttributes();
2871  return ConvertDescriptorToField(name, value, attributes);
2872  case CALLBACKS: {
2873  Object* callback_object = result->GetCallbackObject();
2874  if (callback_object->IsAccessorPair() &&
2875  !AccessorPair::cast(callback_object)->ContainsAccessor()) {
2876  return ConvertDescriptorToField(name, value, attributes);
2877  }
2878  return SetPropertyWithCallback(callback_object,
2879  name,
2880  value,
2881  result->holder(),
2882  strict_mode);
2883  }
2884  case INTERCEPTOR:
2885  return SetPropertyWithInterceptor(name, value, attributes, strict_mode);
2886  case CONSTANT_TRANSITION: {
2887  // If the same constant function is being added we can simply
2888  // transition to the target map.
2889  Map* target_map = result->GetTransitionMap();
2890  DescriptorArray* target_descriptors = target_map->instance_descriptors();
2891  int number = target_descriptors->SearchWithCache(name);
2893  ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION);
2894  JSFunction* function =
2895  JSFunction::cast(target_descriptors->GetValue(number));
2896  if (value == function) {
2897  set_map(target_map);
2898  return value;
2899  }
2900  // Otherwise, replace with a MAP_TRANSITION to a new map with a
2901  // FIELD, even if the value is a constant function.
2902  return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2903  }
2904  case NULL_DESCRIPTOR:
2905  return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2906  case HANDLER:
2907  UNREACHABLE();
2908  return value;
2909  }
2910  UNREACHABLE(); // keep the compiler happy
2911  return value;
2912 }
2913 
2914 
2915 // Set a real local property, even if it is READ_ONLY. If the property is not
2916 // present, add it with attributes NONE. This code is an exact clone of
2917 // SetProperty, with the check for IsReadOnly and the check for a
2918 // callback setter removed. The two lines looking up the LookupResult
2919 // result are also added. If one of the functions is changed, the other
2920 // should be.
2921 // Note that this method cannot be used to set the prototype of a function
2922 // because ConvertDescriptorToField() which is called in "case CALLBACKS:"
2923 // doesn't handle function prototypes correctly.
2925  Handle<JSObject> object,
2926  Handle<String> key,
2927  Handle<Object> value,
2928  PropertyAttributes attributes) {
2930  object->GetIsolate(),
2931  object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
2932  Object);
2933 }
2934 
2935 
2937  String* name,
2938  Object* value,
2939  PropertyAttributes attributes) {
2940  // Make sure that the top context does not change when doing callbacks or
2941  // interceptor calls.
2942  AssertNoContextChange ncc;
2943  Isolate* isolate = GetIsolate();
2944  LookupResult result(isolate);
2945  LocalLookup(name, &result);
2946  // Check access rights if needed.
2947  if (IsAccessCheckNeeded()) {
2948  if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
2949  return SetPropertyWithFailedAccessCheck(&result,
2950  name,
2951  value,
2952  false,
2953  kNonStrictMode);
2954  }
2955  }
2956 
2957  if (IsJSGlobalProxy()) {
2958  Object* proto = GetPrototype();
2959  if (proto->IsNull()) return value;
2960  ASSERT(proto->IsJSGlobalObject());
2962  name,
2963  value,
2964  attributes);
2965  }
2966 
2967  // Check for accessor in prototype chain removed here in clone.
2968  if (!result.IsFound()) {
2969  // Neither properties nor transitions found.
2970  return AddProperty(name, value, attributes, kNonStrictMode);
2971  }
2972 
2973  PropertyDetails details = PropertyDetails(attributes, NORMAL);
2974 
2975  // Check of IsReadOnly removed from here in clone.
2976  switch (result.type()) {
2977  case NORMAL:
2978  return SetNormalizedProperty(name, value, details);
2979  case FIELD:
2980  return FastPropertyAtPut(result.GetFieldIndex(), value);
2981  case MAP_TRANSITION:
2982  if (attributes == result.GetAttributes()) {
2983  // Only use map transition if the attributes match.
2984  return AddFastPropertyUsingMap(result.GetTransitionMap(),
2985  name,
2986  value);
2987  }
2988  return ConvertDescriptorToField(name, value, attributes);
2989  case CONSTANT_FUNCTION:
2990  // Only replace the function if necessary.
2991  if (value == result.GetConstantFunction()) return value;
2992  // Preserve the attributes of this existing property.
2993  attributes = result.GetAttributes();
2994  return ConvertDescriptorToField(name, value, attributes);
2995  case CALLBACKS:
2996  case INTERCEPTOR:
2997  // Override callback in clone
2998  return ConvertDescriptorToField(name, value, attributes);
2999  case CONSTANT_TRANSITION:
3000  // Replace with a MAP_TRANSITION to a new map with a FIELD, even
3001  // if the value is a function.
3002  case NULL_DESCRIPTOR:
3003  return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3004  case HANDLER:
3005  UNREACHABLE();
3006  }
3007  UNREACHABLE(); // keep the compiler happy
3008  return value;
3009 }
3010 
3011 
3013  JSObject* receiver,
3014  String* name,
3015  bool continue_search) {
3016  // Check local property, ignore interceptor.
3017  LookupResult result(GetIsolate());
3018  LocalLookupRealNamedProperty(name, &result);
3019  if (result.IsProperty()) return result.GetAttributes();
3020 
3021  if (continue_search) {
3022  // Continue searching via the prototype chain.
3023  Object* pt = GetPrototype();
3024  if (!pt->IsNull()) {
3025  return JSObject::cast(pt)->
3026  GetPropertyAttributeWithReceiver(receiver, name);
3027  }
3028  }
3029  return ABSENT;
3030 }
3031 
3032 
3034  JSObject* receiver,
3035  String* name,
3036  bool continue_search) {
3037  Isolate* isolate = GetIsolate();
3038 
3039  // Make sure that the top context does not change when doing
3040  // callbacks or interceptor calls.
3041  AssertNoContextChange ncc;
3042 
3043  HandleScope scope(isolate);
3045  Handle<JSObject> receiver_handle(receiver);
3046  Handle<JSObject> holder_handle(this);
3047  Handle<String> name_handle(name);
3048  CustomArguments args(isolate, interceptor->data(), receiver, this);
3049  v8::AccessorInfo info(args.end());
3050  if (!interceptor->query()->IsUndefined()) {
3051  v8::NamedPropertyQuery query =
3052  v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
3053  LOG(isolate,
3054  ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
3055  v8::Handle<v8::Integer> result;
3056  {
3057  // Leaving JavaScript.
3058  VMState state(isolate, EXTERNAL);
3059  result = query(v8::Utils::ToLocal(name_handle), info);
3060  }
3061  if (!result.IsEmpty()) {
3062  ASSERT(result->IsInt32());
3063  return static_cast<PropertyAttributes>(result->Int32Value());
3064  }
3065  } else if (!interceptor->getter()->IsUndefined()) {
3066  v8::NamedPropertyGetter getter =
3067  v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
3068  LOG(isolate,
3069  ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
3070  v8::Handle<v8::Value> result;
3071  {
3072  // Leaving JavaScript.
3073  VMState state(isolate, EXTERNAL);
3074  result = getter(v8::Utils::ToLocal(name_handle), info);
3075  }
3076  if (!result.IsEmpty()) return DONT_ENUM;
3077  }
3078  return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
3079  *name_handle,
3080  continue_search);
3081 }
3082 
3083 
3085  JSReceiver* receiver,
3086  String* key) {
3087  uint32_t index = 0;
3088  if (IsJSObject() && key->AsArrayIndex(&index)) {
3089  return JSObject::cast(this)->HasElementWithReceiver(receiver, index)
3090  ? NONE : ABSENT;
3091  }
3092  // Named property.
3093  LookupResult result(GetIsolate());
3094  Lookup(key, &result);
3095  return GetPropertyAttribute(receiver, &result, key, true);
3096 }
3097 
3098 
3100  LookupResult* result,
3101  String* name,
3102  bool continue_search) {
3103  // Check access rights if needed.
3104  if (IsAccessCheckNeeded()) {
3105  JSObject* this_obj = JSObject::cast(this);
3106  Heap* heap = GetHeap();
3107  if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
3109  receiver, result, name, continue_search);
3110  }
3111  }
3112  if (result->IsProperty()) {
3113  switch (result->type()) {
3114  case NORMAL: // fall through
3115  case FIELD:
3116  case CONSTANT_FUNCTION:
3117  case CALLBACKS:
3118  return result->GetAttributes();
3119  case HANDLER: {
3120  return JSProxy::cast(result->proxy())->GetPropertyAttributeWithHandler(
3121  receiver, name);
3122  }
3123  case INTERCEPTOR:
3124  return result->holder()->GetPropertyAttributeWithInterceptor(
3125  JSObject::cast(receiver), name, continue_search);
3126  default:
3127  UNREACHABLE();
3128  }
3129  }
3130  return ABSENT;
3131 }
3132 
3133 
3135  // Check whether the name is an array index.
3136  uint32_t index = 0;
3137  if (IsJSObject() && name->AsArrayIndex(&index)) {
3138  if (JSObject::cast(this)->HasLocalElement(index)) return NONE;
3139  return ABSENT;
3140  }
3141  // Named property.
3142  LookupResult result(GetIsolate());
3143  LocalLookup(name, &result);
3144  return GetPropertyAttribute(this, &result, name, false);
3145 }
3146 
3147 
3150  Isolate* isolate = obj->GetIsolate();
3151  Map* fast = obj->map();
3152  int index = fast->Hash() % kEntries;
3153  Object* result = get(index);
3154  if (result->IsMap() &&
3155  Map::cast(result)->EquivalentToForNormalization(fast, mode)) {
3156 #ifdef DEBUG
3157  if (FLAG_verify_heap) {
3158  Map::cast(result)->SharedMapVerify();
3159  }
3161  // The cached map should match newly created normalized map bit-by-bit,
3162  // except for the code cache, which can contain some ics which can be
3163  // applied to the shared map.
3164  Object* fresh;
3165  { MaybeObject* maybe_fresh =
3167  if (maybe_fresh->ToObject(&fresh)) {
3168  ASSERT(memcmp(Map::cast(fresh)->address(),
3169  Map::cast(result)->address(),
3170  Map::kCodeCacheOffset) == 0);
3171  int offset = Map::kCodeCacheOffset + kPointerSize;
3172  ASSERT(memcmp(Map::cast(fresh)->address() + offset,
3173  Map::cast(result)->address() + offset,
3174  Map::kSize - offset) == 0);
3175  }
3176  }
3177  }
3178 #endif
3179  return result;
3180  }
3181 
3182  { MaybeObject* maybe_result =
3184  if (!maybe_result->ToObject(&result)) return maybe_result;
3185  }
3186  set(index, result);
3187  isolate->counters()->normalized_maps()->Increment();
3188 
3189  return result;
3190 }
3191 
3192 
3194  int entries = length();
3195  for (int i = 0; i != entries; i++) {
3196  set_undefined(i);
3197  }
3198 }
3199 
3200 
3202  Handle<String> name,
3203  Handle<Code> code) {
3204  Isolate* isolate = object->GetIsolate();
3205  CALL_HEAP_FUNCTION_VOID(isolate,
3206  object->UpdateMapCodeCache(*name, *code));
3207 }
3208 
3209 
3210 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) {
3211  if (map()->is_shared()) {
3212  // Fast case maps are never marked as shared.
3214  // Replace the map with an identical copy that can be safely modified.
3215  Object* obj;
3216  { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES,
3218  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3219  }
3220  GetIsolate()->counters()->normalized_maps()->Increment();
3221 
3222  set_map(Map::cast(obj));
3223  }
3224  return map()->UpdateCodeCache(name, code);
3225 }
3226 
3227 
3230  int expected_additional_properties) {
3231  CALL_HEAP_FUNCTION_VOID(object->GetIsolate(),
3232  object->NormalizeProperties(
3233  mode, expected_additional_properties));
3234 }
3235 
3236 
3238  int expected_additional_properties) {
3239  if (!HasFastProperties()) return this;
3240 
3241  // The global object is always normalized.
3242  ASSERT(!IsGlobalObject());
3243  // JSGlobalProxy must never be normalized
3244  ASSERT(!IsJSGlobalProxy());
3245 
3246  Map* map_of_this = map();
3247 
3248  // Allocate new content.
3249  int property_count = map_of_this->NumberOfDescribedProperties();
3250  if (expected_additional_properties > 0) {
3251  property_count += expected_additional_properties;
3252  } else {
3253  property_count += 2; // Make space for two more properties.
3254  }
3255  StringDictionary* dictionary;
3256  { MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
3257  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3258  }
3259 
3260  DescriptorArray* descs = map_of_this->instance_descriptors();
3261  for (int i = 0; i < descs->number_of_descriptors(); i++) {
3262  PropertyDetails details = descs->GetDetails(i);
3263  switch (details.type()) {
3264  case CONSTANT_FUNCTION: {
3265  PropertyDetails d =
3266  PropertyDetails(details.attributes(), NORMAL, details.index());
3267  Object* value = descs->GetConstantFunction(i);
3268  MaybeObject* maybe_dictionary =
3269  dictionary->Add(descs->GetKey(i), value, d);
3270  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3271  break;
3272  }
3273  case FIELD: {
3274  PropertyDetails d =
3275  PropertyDetails(details.attributes(), NORMAL, details.index());
3276  Object* value = FastPropertyAt(descs->GetFieldIndex(i));
3277  MaybeObject* maybe_dictionary =
3278  dictionary->Add(descs->GetKey(i), value, d);
3279  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3280  break;
3281  }
3282  case CALLBACKS: {
3283  if (!descs->IsProperty(i)) break;
3284  Object* value = descs->GetCallbacksObject(i);
3285  if (value->IsAccessorPair()) {
3286  MaybeObject* maybe_copy =
3288  if (!maybe_copy->To(&value)) return maybe_copy;
3289  }
3290  MaybeObject* maybe_dictionary =
3291  dictionary->Add(descs->GetKey(i), value, details);
3292  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3293  break;
3294  }
3295  case MAP_TRANSITION:
3296  case CONSTANT_TRANSITION:
3297  case NULL_DESCRIPTOR:
3298  case INTERCEPTOR:
3299  break;
3300  case HANDLER:
3301  case NORMAL:
3302  UNREACHABLE();
3303  break;
3304  }
3305  }
3306 
3307  Heap* current_heap = GetHeap();
3308 
3309  // Copy the next enumeration index from instance descriptor.
3310  int index = map_of_this->instance_descriptors()->NextEnumerationIndex();
3311  dictionary->SetNextEnumerationIndex(index);
3312 
3313  Map* new_map;
3314  { MaybeObject* maybe_map =
3315  current_heap->isolate()->context()->global_context()->
3316  normalized_map_cache()->Get(this, mode);
3317  if (!maybe_map->To(&new_map)) return maybe_map;
3318  }
3319 
3320  // We have now successfully allocated all the necessary objects.
3321  // Changes can now be made with the guarantee that all of them take effect.
3322 
3323  // Resize the object in the heap if necessary.
3324  int new_instance_size = new_map->instance_size();
3325  int instance_size_delta = map_of_this->instance_size() - new_instance_size;
3326  ASSERT(instance_size_delta >= 0);
3327  current_heap->CreateFillerObjectAt(this->address() + new_instance_size,
3328  instance_size_delta);
3331  -instance_size_delta);
3332  }
3333 
3334 
3335  set_map(new_map);
3336  new_map->clear_instance_descriptors();
3337 
3338  set_properties(dictionary);
3339 
3340  current_heap->isolate()->counters()->props_to_dictionary()->Increment();
3341 
3342 #ifdef DEBUG
3343  if (FLAG_trace_normalization) {
3344  PrintF("Object properties have been normalized:\n");
3345  Print();
3346  }
3347 #endif
3348  return this;
3349 }
3350 
3351 
3353  int unused_property_fields) {
3355  object->GetIsolate(),
3356  object->TransformToFastProperties(unused_property_fields));
3357 }
3358 
3359 
3360 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
3361  if (HasFastProperties()) return this;
3362  ASSERT(!IsGlobalObject());
3363  return property_dictionary()->
3364  TransformPropertiesToFastFor(this, unused_property_fields);
3365 }
3366 
3367 
3369  Handle<JSObject> object) {
3370  CALL_HEAP_FUNCTION(object->GetIsolate(),
3371  object->NormalizeElements(),
3373 }
3374 
3375 
3378 
3379  // Find the backing store.
3380  FixedArrayBase* array = FixedArrayBase::cast(elements());
3381  Map* old_map = array->map();
3382  bool is_arguments =
3383  (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
3384  if (is_arguments) {
3385  array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
3386  }
3387  if (array->IsDictionary()) return array;
3388 
3392  // Compute the effective length and allocate a new backing store.
3393  int length = IsJSArray()
3394  ? Smi::cast(JSArray::cast(this)->length())->value()
3395  : array->length();
3396  int old_capacity = 0;
3397  int used_elements = 0;
3398  GetElementsCapacityAndUsage(&old_capacity, &used_elements);
3399  SeededNumberDictionary* dictionary = NULL;
3400  { Object* object;
3401  MaybeObject* maybe = SeededNumberDictionary::Allocate(used_elements);
3402  if (!maybe->ToObject(&object)) return maybe;
3403  dictionary = SeededNumberDictionary::cast(object);
3404  }
3405 
3406  // Copy the elements to the new backing store.
3407  bool has_double_elements = array->IsFixedDoubleArray();
3408  for (int i = 0; i < length; i++) {
3409  Object* value = NULL;
3410  if (has_double_elements) {
3411  FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
3412  if (double_array->is_the_hole(i)) {
3413  value = GetIsolate()->heap()->the_hole_value();
3414  } else {
3415  // Objects must be allocated in the old object space, since the
3416  // overall number of HeapNumbers needed for the conversion might
3417  // exceed the capacity of new space, and we would fail repeatedly
3418  // trying to convert the FixedDoubleArray.
3419  MaybeObject* maybe_value_object =
3420  GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
3421  if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
3422  }
3423  } else {
3425  value = FixedArray::cast(array)->get(i);
3426  }
3427  PropertyDetails details = PropertyDetails(NONE, NORMAL);
3428  if (!value->IsTheHole()) {
3429  Object* result;
3430  MaybeObject* maybe_result =
3431  dictionary->AddNumberEntry(i, value, details);
3432  if (!maybe_result->ToObject(&result)) return maybe_result;
3433  dictionary = SeededNumberDictionary::cast(result);
3434  }
3435  }
3436 
3437  // Switch to using the dictionary as the backing storage for elements.
3438  if (is_arguments) {
3439  FixedArray::cast(elements())->set(1, dictionary);
3440  } else {
3441  // Set the new map first to satify the elements type assert in
3442  // set_elements().
3443  Object* new_map;
3444  MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(),
3446  if (!maybe->ToObject(&new_map)) return maybe;
3447  set_map(Map::cast(new_map));
3448  set_elements(dictionary);
3449  }
3450 
3451  old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->
3452  Increment();
3453 
3454 #ifdef DEBUG
3455  if (FLAG_trace_normalization) {
3456  PrintF("Object elements have been normalized:\n");
3457  Print();
3458  }
3459 #endif
3460 
3462  return dictionary;
3463 }
3464 
3465 
3467  Isolate* isolate = GetIsolate();
3468 
3469  int hash_value;
3470  int attempts = 0;
3471  do {
3472  // Generate a random 32-bit hash value but limit range to fit
3473  // within a smi.
3474  hash_value = V8::RandomPrivate(isolate) & Smi::kMaxValue;
3475  attempts++;
3476  } while (hash_value == 0 && attempts < 30);
3477  hash_value = hash_value != 0 ? hash_value : 1; // never return 0
3478 
3479  return Smi::FromInt(hash_value);
3480 }
3481 
3482 
3484  MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3485  hash);
3486  if (maybe->IsFailure()) return maybe;
3487  return this;
3488 }
3489 
3490 
3492  CALL_AND_RETRY(obj->GetIsolate(),
3493  obj->GetIdentityHash(ALLOW_CREATION),
3494  return Smi::cast(__object__)->value(),
3495  return 0);
3496 }
3497 
3498 
3500  Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol());
3501  if (stored_value->IsSmi()) return stored_value;
3502 
3503  // Do not generate permanent identity hash code if not requested.
3504  if (flag == OMIT_CREATION) return GetHeap()->undefined_value();
3505 
3506  Smi* hash = GenerateIdentityHash();
3507  MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3508  hash);
3509  if (result->IsFailure()) return result;
3510  if (result->ToObjectUnchecked()->IsUndefined()) {
3511  // Trying to get hash of detached proxy.
3512  return Smi::FromInt(0);
3513  }
3514  return hash;
3515 }
3516 
3517 
3519  Object* hash = this->hash();
3520  if (!hash->IsSmi() && flag == ALLOW_CREATION) {
3521  hash = GenerateIdentityHash();
3522  set_hash(hash);
3523  }
3524  return hash;
3525 }
3526 
3527 
3529  if (IsJSGlobalProxy()) {
3530  // For a proxy, use the prototype as target object.
3531  Object* proxy_parent = GetPrototype();
3532  // If the proxy is detached, return undefined.
3533  if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3534  ASSERT(proxy_parent->IsJSGlobalObject());
3535  return JSObject::cast(proxy_parent)->GetHiddenProperty(key);
3536  }
3537  ASSERT(!IsJSGlobalProxy());
3538  MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
3539  ASSERT(!hidden_lookup->IsFailure()); // No failure when passing false as arg.
3540  if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) {
3541  return GetHeap()->undefined_value();
3542  }
3543  StringDictionary* dictionary =
3544  StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
3545  int entry = dictionary->FindEntry(key);
3546  if (entry == StringDictionary::kNotFound) return GetHeap()->undefined_value();
3547  return dictionary->ValueAt(entry);
3548 }
3549 
3550 
3552  Handle<String> key,
3553  Handle<Object> value) {
3554  CALL_HEAP_FUNCTION(obj->GetIsolate(),
3555  obj->SetHiddenProperty(*key, *value),
3556  Object);
3557 }
3558 
3559 
3560 MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
3561  if (IsJSGlobalProxy()) {
3562  // For a proxy, use the prototype as target object.
3563  Object* proxy_parent = GetPrototype();
3564  // If the proxy is detached, return undefined.
3565  if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3566  ASSERT(proxy_parent->IsJSGlobalObject());
3567  return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value);
3568  }
3569  ASSERT(!IsJSGlobalProxy());
3570  MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(true);
3571  StringDictionary* dictionary;
3572  if (!hidden_lookup->To<StringDictionary>(&dictionary)) return hidden_lookup;
3573 
3574  // If it was found, check if the key is already in the dictionary.
3575  int entry = dictionary->FindEntry(key);
3576  if (entry != StringDictionary::kNotFound) {
3577  // If key was found, just update the value.
3578  dictionary->ValueAtPut(entry, value);
3579  return this;
3580  }
3581  // Key was not already in the dictionary, so add the entry.
3582  MaybeObject* insert_result = dictionary->Add(key,
3583  value,
3584  PropertyDetails(NONE, NORMAL));
3585  StringDictionary* new_dict;
3586  if (!insert_result->To<StringDictionary>(&new_dict)) return insert_result;
3587  if (new_dict != dictionary) {
3588  // If adding the key expanded the dictionary (i.e., Add returned a new
3589  // dictionary), store it back to the object.
3590  MaybeObject* store_result = SetHiddenPropertiesDictionary(new_dict);
3591  if (store_result->IsFailure()) return store_result;
3592  }
3593  // Return this to mark success.
3594  return this;
3595 }
3596 
3597 
3599  if (IsJSGlobalProxy()) {
3600  // For a proxy, use the prototype as target object.
3601  Object* proxy_parent = GetPrototype();
3602  // If the proxy is detached, return immediately.
3603  if (proxy_parent->IsNull()) return;
3604  ASSERT(proxy_parent->IsJSGlobalObject());
3605  JSObject::cast(proxy_parent)->DeleteHiddenProperty(key);
3606  return;
3607  }
3608  MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
3609  ASSERT(!hidden_lookup->IsFailure()); // No failure when passing false as arg.
3610  if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) return;
3611  StringDictionary* dictionary =
3612  StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
3613  int entry = dictionary->FindEntry(key);
3614  if (entry == StringDictionary::kNotFound) {
3615  // Key wasn't in dictionary. Deletion is a success.
3616  return;
3617  }
3618  // Key was in the dictionary. Remove it.
3619  dictionary->DeleteProperty(entry, JSReceiver::FORCE_DELETION);
3620 }
3621 
3622 
3625  GetHeap()->hidden_symbol(),
3626  false) != ABSENT;
3627 }
3628 
3629 
3630 MaybeObject* JSObject::GetHiddenPropertiesDictionary(bool create_if_absent) {
3631  ASSERT(!IsJSGlobalProxy());
3632  if (HasFastProperties()) {
3633  // If the object has fast properties, check whether the first slot
3634  // in the descriptor array matches the hidden symbol. Since the
3635  // hidden symbols hash code is zero (and no other string has hash
3636  // code zero) it will always occupy the first entry if present.
3637  DescriptorArray* descriptors = this->map()->instance_descriptors();
3638  if ((descriptors->number_of_descriptors() > 0) &&
3639  (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
3640  if (descriptors->GetType(0) == FIELD) {
3641  Object* hidden_store =
3642  this->FastPropertyAt(descriptors->GetFieldIndex(0));
3643  return StringDictionary::cast(hidden_store);
3644  } else {
3645  ASSERT(descriptors->GetType(0) == NULL_DESCRIPTOR ||
3646  descriptors->GetType(0) == MAP_TRANSITION);
3647  }
3648  }
3649  } else {
3650  PropertyAttributes attributes;
3651  // You can't install a getter on a property indexed by the hidden symbol,
3652  // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3653  // object.
3654  Object* lookup =
3656  GetHeap()->hidden_symbol(),
3657  &attributes)->ToObjectUnchecked();
3658  if (!lookup->IsUndefined()) {
3659  return StringDictionary::cast(lookup);
3660  }
3661  }
3662  if (!create_if_absent) return GetHeap()->undefined_value();
3663  const int kInitialSize = 5;
3664  MaybeObject* dict_alloc = StringDictionary::Allocate(kInitialSize);
3665  StringDictionary* dictionary;
3666  if (!dict_alloc->To<StringDictionary>(&dictionary)) return dict_alloc;
3667  // Using AddProperty or SetPropertyPostInterceptor here could fail, because
3668  // object might be non-extensible.
3669  return HasFastProperties()
3670  ? AddFastProperty(GetHeap()->hidden_symbol(), dictionary, DONT_ENUM)
3671  : AddSlowProperty(GetHeap()->hidden_symbol(), dictionary, DONT_ENUM);
3672 }
3673 
3674 
3675 MaybeObject* JSObject::SetHiddenPropertiesDictionary(
3676  StringDictionary* dictionary) {
3677  ASSERT(!IsJSGlobalProxy());
3679  if (HasFastProperties()) {
3680  // If the object has fast properties, check whether the first slot
3681  // in the descriptor array matches the hidden symbol. Since the
3682  // hidden symbols hash code is zero (and no other string has hash
3683  // code zero) it will always occupy the first entry if present.
3684  DescriptorArray* descriptors = this->map()->instance_descriptors();
3685  if ((descriptors->number_of_descriptors() > 0) &&
3686  (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
3687  if (descriptors->GetType(0) == FIELD) {
3688  this->FastPropertyAtPut(descriptors->GetFieldIndex(0), dictionary);
3689  return this;
3690  } else {
3691  ASSERT(descriptors->GetType(0) == NULL_DESCRIPTOR ||
3692  descriptors->GetType(0) == MAP_TRANSITION);
3693  }
3694  }
3695  }
3696  MaybeObject* store_result =
3697  SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3698  dictionary,
3699  DONT_ENUM,
3700  kNonStrictMode);
3701  if (store_result->IsFailure()) return store_result;
3702  return this;
3703 }
3704 
3705 
3706 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
3707  DeleteMode mode) {
3708  // Check local property, ignore interceptor.
3709  LookupResult result(GetIsolate());
3710  LocalLookupRealNamedProperty(name, &result);
3711  if (!result.IsProperty()) return GetHeap()->true_value();
3712 
3713  // Normalize object if needed.
3714  Object* obj;
3715  { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3716  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3717  }
3718 
3719  return DeleteNormalizedProperty(name, mode);
3720 }
3721 
3722 
3723 MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) {
3724  Isolate* isolate = GetIsolate();
3725  HandleScope scope(isolate);
3726  Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
3727  Handle<String> name_handle(name);
3728  Handle<JSObject> this_handle(this);
3729  if (!interceptor->deleter()->IsUndefined()) {
3730  v8::NamedPropertyDeleter deleter =
3731  v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter());
3732  LOG(isolate,
3733  ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name));
3734  CustomArguments args(isolate, interceptor->data(), this, this);
3735  v8::AccessorInfo info(args.end());
3736  v8::Handle<v8::Boolean> result;
3737  {
3738  // Leaving JavaScript.
3739  VMState state(isolate, EXTERNAL);
3740  result = deleter(v8::Utils::ToLocal(name_handle), info);
3741  }
3743  if (!result.IsEmpty()) {
3744  ASSERT(result->IsBoolean());
3745  return *v8::Utils::OpenHandle(*result);
3746  }
3747  }
3748  MaybeObject* raw_result =
3749  this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION);
3751  return raw_result;
3752 }
3753 
3754 
3755 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
3756  Isolate* isolate = GetIsolate();
3757  Heap* heap = isolate->heap();
3758  // Make sure that the top context does not change when doing
3759  // callbacks or interceptor calls.
3760  AssertNoContextChange ncc;
3761  HandleScope scope(isolate);
3762  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
3763  if (interceptor->deleter()->IsUndefined()) return heap->false_value();
3764  v8::IndexedPropertyDeleter deleter =
3765  v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
3766  Handle<JSObject> this_handle(this);
3767  LOG(isolate,
3768  ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
3769  CustomArguments args(isolate, interceptor->data(), this, this);
3770  v8::AccessorInfo info(args.end());
3771  v8::Handle<v8::Boolean> result;
3772  {
3773  // Leaving JavaScript.
3774  VMState state(isolate, EXTERNAL);
3775  result = deleter(index, info);
3776  }
3778  if (!result.IsEmpty()) {
3779  ASSERT(result->IsBoolean());
3780  return *v8::Utils::OpenHandle(*result);
3781  }
3782  MaybeObject* raw_result = this_handle->GetElementsAccessor()->Delete(
3783  *this_handle,
3784  index,
3785  NORMAL_DELETION);
3787  return raw_result;
3788 }
3789 
3790 
3792  uint32_t index) {
3793  CALL_HEAP_FUNCTION(obj->GetIsolate(),
3794  obj->DeleteElement(index, JSObject::NORMAL_DELETION),
3795  Object);
3796 }
3797 
3798 
3799 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
3800  Isolate* isolate = GetIsolate();
3801  // Check access rights if needed.
3802  if (IsAccessCheckNeeded() &&
3803  !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
3805  return isolate->heap()->false_value();
3806  }
3807 
3808  if (IsJSGlobalProxy()) {
3809  Object* proto = GetPrototype();
3810  if (proto->IsNull()) return isolate->heap()->false_value();
3811  ASSERT(proto->IsJSGlobalObject());
3812  return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
3813  }
3814 
3815  if (HasIndexedInterceptor()) {
3816  // Skip interceptor if forcing deletion.
3817  if (mode != FORCE_DELETION) {
3818  return DeleteElementWithInterceptor(index);
3819  }
3821  }
3822 
3823  return GetElementsAccessor()->Delete(this, index, mode);
3824 }
3825 
3826 
3828  Handle<String> prop) {
3829  CALL_HEAP_FUNCTION(obj->GetIsolate(),
3830  obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
3831  Object);
3832 }
3833 
3834 
3835 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
3836  Isolate* isolate = GetIsolate();
3837  // ECMA-262, 3rd, 8.6.2.5
3838  ASSERT(name->IsString());
3839 
3840  // Check access rights if needed.
3841  if (IsAccessCheckNeeded() &&
3842  !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) {
3844  return isolate->heap()->false_value();
3845  }
3846 
3847  if (IsJSGlobalProxy()) {
3848  Object* proto = GetPrototype();
3849  if (proto->IsNull()) return isolate->heap()->false_value();
3850  ASSERT(proto->IsJSGlobalObject());
3851  return JSGlobalObject::cast(proto)->DeleteProperty(name, mode);
3852  }
3853 
3854  uint32_t index = 0;
3855  if (name->AsArrayIndex(&index)) {
3856  return DeleteElement(index, mode);
3857  } else {
3858  LookupResult result(isolate);
3859  LocalLookup(name, &result);
3860  if (!result.IsProperty()) return isolate->heap()->true_value();
3861  // Ignore attributes if forcing a deletion.
3862  if (result.IsDontDelete() && mode != FORCE_DELETION) {
3863  if (mode == STRICT_DELETION) {
3864  // Deleting a non-configurable property in strict mode.
3865  HandleScope scope(isolate);
3866  Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
3867  return isolate->Throw(*isolate->factory()->NewTypeError(
3868  "strict_delete_property", HandleVector(args, 2)));
3869  }
3870  return isolate->heap()->false_value();
3871  }
3872  // Check for interceptor.
3873  if (result.type() == INTERCEPTOR) {
3874  // Skip interceptor if forcing a deletion.
3875  if (mode == FORCE_DELETION) {
3876  return DeletePropertyPostInterceptor(name, mode);
3877  }
3878  return DeletePropertyWithInterceptor(name);
3879  }
3880  // Normalize object if needed.
3881  Object* obj;
3882  { MaybeObject* maybe_obj =
3884  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3885  }
3886  // Make sure the properties are normalized before removing the entry.
3887  return DeleteNormalizedProperty(name, mode);
3888  }
3889 }
3890 
3891 
3892 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) {
3893  if (IsJSProxy()) {
3894  return JSProxy::cast(this)->DeleteElementWithHandler(index, mode);
3895  }
3896  return JSObject::cast(this)->DeleteElement(index, mode);
3897 }
3898 
3899 
3900 MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
3901  if (IsJSProxy()) {
3902  return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
3903  }
3904  return JSObject::cast(this)->DeleteProperty(name, mode);
3905 }
3906 
3907 
3908 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
3909  ElementsKind kind,
3910  Object* object) {
3912  kind == DICTIONARY_ELEMENTS);
3913  if (IsFastObjectElementsKind(kind)) {
3914  int length = IsJSArray()
3915  ? Smi::cast(JSArray::cast(this)->length())->value()
3916  : elements->length();
3917  for (int i = 0; i < length; ++i) {
3918  Object* element = elements->get(i);
3919  if (!element->IsTheHole() && element == object) return true;
3920  }
3921  } else {
3922  Object* key =
3924  if (!key->IsUndefined()) return true;
3925  }
3926  return false;
3927 }
3928 
3929 
3930 // Check whether this object references another object.
3932  Map* map_of_this = map();
3933  Heap* heap = GetHeap();
3934  AssertNoAllocation no_alloc;
3935 
3936  // Is the object the constructor for this object?
3937  if (map_of_this->constructor() == obj) {
3938  return true;
3939  }
3940 
3941  // Is the object the prototype for this object?
3942  if (map_of_this->prototype() == obj) {
3943  return true;
3944  }
3945 
3946  // Check if the object is among the named properties.
3947  Object* key = SlowReverseLookup(obj);
3948  if (!key->IsUndefined()) {
3949  return true;
3950  }
3951 
3952  // Check if the object is among the indexed properties.
3953  ElementsKind kind = GetElementsKind();
3954  switch (kind) {
3960  case EXTERNAL_INT_ELEMENTS:
3964  case FAST_DOUBLE_ELEMENTS:
3966  // Raw pixels and external arrays do not reference other
3967  // objects.
3968  break;
3969  case FAST_SMI_ELEMENTS:
3971  break;
3972  case FAST_ELEMENTS:
3973  case FAST_HOLEY_ELEMENTS:
3974  case DICTIONARY_ELEMENTS: {
3975  FixedArray* elements = FixedArray::cast(this->elements());
3976  if (ReferencesObjectFromElements(elements, kind, obj)) return true;
3977  break;
3978  }
3980  FixedArray* parameter_map = FixedArray::cast(elements());
3981  // Check the mapped parameters.
3982  int length = parameter_map->length();
3983  for (int i = 2; i < length; ++i) {
3984  Object* value = parameter_map->get(i);
3985  if (!value->IsTheHole() && value == obj) return true;
3986  }
3987  // Check the arguments.
3988  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
3989  kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
3991  if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
3992  break;
3993  }
3994  }
3995 
3996  // For functions check the context.
3997  if (IsJSFunction()) {
3998  // Get the constructor function for arguments array.
3999  JSObject* arguments_boilerplate =
4000  heap->isolate()->context()->global_context()->
4001  arguments_boilerplate();
4002  JSFunction* arguments_function =
4003  JSFunction::cast(arguments_boilerplate->map()->constructor());
4004 
4005  // Get the context and don't check if it is the global context.
4006  JSFunction* f = JSFunction::cast(this);
4007  Context* context = f->context();
4008  if (context->IsGlobalContext()) {
4009  return false;
4010  }
4011 
4012  // Check the non-special context slots.
4013  for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
4014  // Only check JS objects.
4015  if (context->get(i)->IsJSObject()) {
4016  JSObject* ctxobj = JSObject::cast(context->get(i));
4017  // If it is an arguments array check the content.
4018  if (ctxobj->map()->constructor() == arguments_function) {
4019  if (ctxobj->ReferencesObject(obj)) {
4020  return true;
4021  }
4022  } else if (ctxobj == obj) {
4023  return true;
4024  }
4025  }
4026  }
4027 
4028  // Check the context extension (if any) if it can have references.
4029  if (context->has_extension() && !context->IsCatchContext()) {
4030  return JSObject::cast(context->extension())->ReferencesObject(obj);
4031  }
4032  }
4033 
4034  // No references to object.
4035  return false;
4036 }
4037 
4038 
4040  CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object);
4041 }
4042 
4043 
4045  Isolate* isolate = GetIsolate();
4046  if (IsAccessCheckNeeded() &&
4047  !isolate->MayNamedAccess(this,
4048  isolate->heap()->undefined_value(),
4049  v8::ACCESS_KEYS)) {
4050  isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
4051  return isolate->heap()->false_value();
4052  }
4053 
4054  if (IsJSGlobalProxy()) {
4055  Object* proto = GetPrototype();
4056  if (proto->IsNull()) return this;
4057  ASSERT(proto->IsJSGlobalObject());
4058  return JSObject::cast(proto)->PreventExtensions();
4059  }
4060 
4061  // It's not possible to seal objects with external array elements
4062  if (HasExternalArrayElements()) {
4063  HandleScope scope(isolate);
4064  Handle<Object> object(this);
4065  Handle<Object> error =
4066  isolate->factory()->NewTypeError(
4067  "cant_prevent_ext_external_array_elements",
4068  HandleVector(&object, 1));
4069  return isolate->Throw(*error);
4070  }
4071 
4072  // If there are fast elements we normalize.
4073  SeededNumberDictionary* dictionary = NULL;
4074  { MaybeObject* maybe = NormalizeElements();
4075  if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe;
4076  }
4078  // Make sure that we never go back to fast case.
4079  dictionary->set_requires_slow_elements();
4080 
4081  // Do a map transition, other objects with this map may still
4082  // be extensible.
4083  Map* new_map;
4084  { MaybeObject* maybe =
4086  if (!maybe->To<Map>(&new_map)) return maybe;
4087  }
4088  new_map->set_is_extensible(false);
4089  set_map(new_map);
4090  ASSERT(!map()->is_extensible());
4091  return new_map;
4092 }
4093 
4094 
4095 // Tests for the fast common case for property enumeration:
4096 // - This object and all prototypes has an enum cache (which means that
4097 // it is no proxy, has no interceptors and needs no access checks).
4098 // - This object has no elements.
4099 // - No prototype has enumerable properties/elements.
4101  Heap* heap = GetHeap();
4102  for (Object* o = this;
4103  o != heap->null_value();
4104  o = JSObject::cast(o)->GetPrototype()) {
4105  if (!o->IsJSObject()) return false;
4106  JSObject* curr = JSObject::cast(o);
4107  if (!curr->map()->instance_descriptors()->HasEnumCache()) return false;
4108  ASSERT(!curr->HasNamedInterceptor());
4109  ASSERT(!curr->HasIndexedInterceptor());
4110  ASSERT(!curr->IsAccessCheckNeeded());
4111  if (curr->NumberOfEnumElements() > 0) return false;
4112  if (curr != this) {
4113  FixedArray* curr_fixed_array =
4114  FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache());
4115  if (curr_fixed_array->length() > 0) return false;
4116  }
4117  }
4118  return true;
4119 }
4120 
4121 
4123  int result = 0;
4124  DescriptorArray* descs = instance_descriptors();
4125  for (int i = 0; i < descs->number_of_descriptors(); i++) {
4126  PropertyDetails details = descs->GetDetails(i);
4127  if (descs->IsProperty(i) && (details.attributes() & filter) == 0) {
4128  result++;
4129  }
4130  }
4131  return result;
4132 }
4133 
4134 
4136  DescriptorArray* descs = instance_descriptors();
4137  for (int i = 0; i < descs->number_of_descriptors(); i++) {
4138  if (name->Equals(descs->GetKey(i)) && !descs->IsNullDescriptor(i)) {
4139  return descs->GetFieldIndex(i);
4140  }
4141  }
4142  return -1;
4143 }
4144 
4145 
4147  int max_index = -1;
4148  DescriptorArray* descs = instance_descriptors();
4149  for (int i = 0; i < descs->number_of_descriptors(); i++) {
4150  if (descs->GetType(i) == FIELD) {
4151  int current_index = descs->GetFieldIndex(i);
4152  if (current_index > max_index) max_index = current_index;
4153  }
4154  }
4155  return max_index + 1;
4156 }
4157 
4158 
4160  DescriptorArray* descs = instance_descriptors();
4161  for (int i = 0; i < descs->number_of_descriptors(); i++) {
4162  if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
4163  return descs->GetCallbacks(i);
4164  }
4165  }
4166  return NULL;
4167 }
4168 
4169 
4170 void JSReceiver::LocalLookup(String* name, LookupResult* result) {
4171  ASSERT(name->IsString());
4172 
4173  Heap* heap = GetHeap();
4174 
4175  if (IsJSGlobalProxy()) {
4176  Object* proto = GetPrototype();
4177  if (proto->IsNull()) return result->NotFound();
4178  ASSERT(proto->IsJSGlobalObject());
4179  return JSReceiver::cast(proto)->LocalLookup(name, result);
4180  }
4181 
4182  if (IsJSProxy()) {
4183  result->HandlerResult(JSProxy::cast(this));
4184  return;
4185  }
4186 
4187  // Do not use inline caching if the object is a non-global object
4188  // that requires access checks.
4189  if (IsAccessCheckNeeded()) {
4190  result->DisallowCaching();
4191  }
4192 
4193  JSObject* js_object = JSObject::cast(this);
4194 
4195  // Check __proto__ before interceptor.
4196  if (name->Equals(heap->Proto_symbol()) && !IsJSContextExtensionObject()) {
4197  result->ConstantResult(js_object);
4198  return;
4199  }
4200 
4201  // Check for lookup interceptor except when bootstrapping.
4202  if (js_object->HasNamedInterceptor() &&
4203  !heap->isolate()->bootstrapper()->IsActive()) {
4204  result->InterceptorResult(js_object);
4205  return;
4206  }
4207 
4208  js_object->LocalLookupRealNamedProperty(name, result);
4209 }
4210 
4211 
4212 void JSReceiver::Lookup(String* name, LookupResult* result) {
4213  // Ecma-262 3rd 8.6.2.4
4214  Heap* heap = GetHeap();
4215  for (Object* current = this;
4216  current != heap->null_value();
4217  current = JSObject::cast(current)->GetPrototype()) {
4218  JSReceiver::cast(current)->LocalLookup(name, result);
4219  if (result->IsProperty()) return;
4220  }
4221  result->NotFound();
4222 }
4223 
4224 
4225 // Search object and its prototype chain for callback properties.
4226 void JSObject::LookupCallback(String* name, LookupResult* result) {
4227  Heap* heap = GetHeap();
4228  for (Object* current = this;
4229  current != heap->null_value() && current->IsJSObject();
4230  current = JSObject::cast(current)->GetPrototype()) {
4231  JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
4232  if (result->IsFound() && result->type() == CALLBACKS) return;
4233  }
4234  result->NotFound();
4235 }
4236 
4237 
4238 // Try to update an accessor in an elements dictionary. Return true if the
4239 // update succeeded, and false otherwise.
4240 static bool UpdateGetterSetterInDictionary(
4241  SeededNumberDictionary* dictionary,
4242  uint32_t index,
4243  Object* getter,
4244  Object* setter,
4245  PropertyAttributes attributes) {
4246  int entry = dictionary->FindEntry(index);
4247  if (entry != SeededNumberDictionary::kNotFound) {
4248  Object* result = dictionary->ValueAt(entry);
4249  PropertyDetails details = dictionary->DetailsAt(entry);
4250  if (details.type() == CALLBACKS && result->IsAccessorPair()) {
4251  ASSERT(!details.IsDontDelete());
4252  if (details.attributes() != attributes) {
4253  dictionary->DetailsAtPut(entry,
4254  PropertyDetails(attributes, CALLBACKS, index));
4255  }
4256  AccessorPair::cast(result)->SetComponents(getter, setter);
4257  return true;
4258  }
4259  }
4260  return false;
4261 }
4262 
4263 
4264 MaybeObject* JSObject::DefineElementAccessor(uint32_t index,
4265  Object* getter,
4266  Object* setter,
4267  PropertyAttributes attributes) {
4268  switch (GetElementsKind()) {
4269  case FAST_SMI_ELEMENTS:
4270  case FAST_ELEMENTS:
4271  case FAST_DOUBLE_ELEMENTS:
4273  case FAST_HOLEY_ELEMENTS:
4275  break;
4281  case EXTERNAL_INT_ELEMENTS:
4285  // Ignore getters and setters on pixel and external array elements.
4286  return GetHeap()->undefined_value();
4287  case DICTIONARY_ELEMENTS:
4288  if (UpdateGetterSetterInDictionary(element_dictionary(),
4289  index,
4290  getter,
4291  setter,
4292  attributes)) {
4293  return GetHeap()->undefined_value();
4294  }
4295  break;
4297  // Ascertain whether we have read-only properties or an existing
4298  // getter/setter pair in an arguments elements dictionary backing
4299  // store.
4300  FixedArray* parameter_map = FixedArray::cast(elements());
4301  uint32_t length = parameter_map->length();
4302  Object* probe =
4303  index < (length - 2) ? parameter_map->get(index + 2) : NULL;
4304  if (probe == NULL || probe->IsTheHole()) {
4305  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4306  if (arguments->IsDictionary()) {
4307  SeededNumberDictionary* dictionary =
4308  SeededNumberDictionary::cast(arguments);
4309  if (UpdateGetterSetterInDictionary(dictionary,
4310  index,
4311  getter,
4312  setter,
4313  attributes)) {
4314  return GetHeap()->undefined_value();
4315  }
4316  }
4317  }
4318  break;
4319  }
4320  }
4321 
4322  AccessorPair* accessors;
4323  { MaybeObject* maybe_accessors = GetHeap()->AllocateAccessorPair();
4324  if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4325  }
4326  accessors->SetComponents(getter, setter);
4327 
4328  return SetElementCallback(index, accessors, attributes);
4329 }
4330 
4331 
4332 MaybeObject* JSObject::CreateAccessorPairFor(String* name) {
4333  LookupResult result(GetHeap()->isolate());
4334  LocalLookupRealNamedProperty(name, &result);
4335  if (result.IsProperty() && result.type() == CALLBACKS) {
4336  // Note that the result can actually have IsDontDelete() == true when we
4337  // e.g. have to fall back to the slow case while adding a setter after
4338  // successfully reusing a map transition for a getter. Nevertheless, this is
4339  // OK, because the assertion only holds for the whole addition of both
4340  // accessors, not for the addition of each part. See first comment in
4341  // DefinePropertyAccessor below.
4342  Object* obj = result.GetCallbackObject();
4343  if (obj->IsAccessorPair()) {
4345  }
4346  }
4347  return GetHeap()->AllocateAccessorPair();
4348 }
4349 
4350 
4351 MaybeObject* JSObject::DefinePropertyAccessor(String* name,
4352  Object* getter,
4353  Object* setter,
4354  PropertyAttributes attributes) {
4355  // We could assert that the property is configurable here, but we would need
4356  // to do a lookup, which seems to be a bit of overkill.
4357  Heap* heap = GetHeap();
4358  bool only_attribute_changes = getter->IsNull() && setter->IsNull();
4359  if (HasFastProperties() && !only_attribute_changes) {
4360  MaybeObject* getterOk = heap->undefined_value();
4361  if (!getter->IsNull()) {
4362  getterOk = DefineFastAccessor(name, ACCESSOR_GETTER, getter, attributes);
4363  if (getterOk->IsFailure()) return getterOk;
4364  }
4365 
4366  MaybeObject* setterOk = heap->undefined_value();
4367  if (getterOk != heap->null_value() && !setter->IsNull()) {
4368  setterOk = DefineFastAccessor(name, ACCESSOR_SETTER, setter, attributes);
4369  if (setterOk->IsFailure()) return setterOk;
4370  }
4371 
4372  if (getterOk != heap->null_value() && setterOk != heap->null_value()) {
4373  return heap->undefined_value();
4374  }
4375  }
4376 
4377  AccessorPair* accessors;
4378  { MaybeObject* maybe_accessors = CreateAccessorPairFor(name);
4379  if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4380  }
4381  accessors->SetComponents(getter, setter);
4382  return SetPropertyCallback(name, accessors, attributes);
4383 }
4384 
4385 
4386 bool JSObject::CanSetCallback(String* name) {
4387  ASSERT(!IsAccessCheckNeeded() ||
4388  GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
4389 
4390  // Check if there is an API defined callback object which prohibits
4391  // callback overwriting in this object or its prototype chain.
4392  // This mechanism is needed for instance in a browser setting, where
4393  // certain accessors such as window.location should not be allowed
4394  // to be overwritten because allowing overwriting could potentially
4395  // cause security problems.
4396  LookupResult callback_result(GetIsolate());
4397  LookupCallback(name, &callback_result);
4398  if (callback_result.IsProperty()) {
4399  Object* obj = callback_result.GetCallbackObject();
4400  if (obj->IsAccessorInfo() &&
4402  return false;
4403  }
4404  }
4405 
4406  return true;
4407 }
4408 
4409 
4410 MaybeObject* JSObject::SetElementCallback(uint32_t index,
4411  Object* structure,
4412  PropertyAttributes attributes) {
4413  PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
4414 
4415  // Normalize elements to make this operation simple.
4416  SeededNumberDictionary* dictionary;
4417  { MaybeObject* maybe_dictionary = NormalizeElements();
4418  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4419  }
4421 
4422  // Update the dictionary with the new CALLBACKS property.
4423  { MaybeObject* maybe_dictionary = dictionary->Set(index, structure, details);
4424  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4425  }
4426 
4427  dictionary->set_requires_slow_elements();
4428  // Update the dictionary backing store on the object.
4429  if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
4430  // Also delete any parameter alias.
4431  //
4432  // TODO(kmillikin): when deleting the last parameter alias we could
4433  // switch to a direct backing store without the parameter map. This
4434  // would allow GC of the context.
4435  FixedArray* parameter_map = FixedArray::cast(elements());
4436  if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
4437  parameter_map->set(index + 2, GetHeap()->the_hole_value());
4438  }
4439  parameter_map->set(1, dictionary);
4440  } else {
4441  set_elements(dictionary);
4442  }
4443 
4444  return GetHeap()->undefined_value();
4445 }
4446 
4447 
4448 MaybeObject* JSObject::SetPropertyCallback(String* name,
4449  Object* structure,
4450  PropertyAttributes attributes) {
4451  // Normalize object to make this operation simple.
4452  { MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
4453  if (maybe_ok->IsFailure()) return maybe_ok;
4454  }
4455 
4456  // For the global object allocate a new map to invalidate the global inline
4457  // caches which have a global property cell reference directly in the code.
4458  if (IsGlobalObject()) {
4459  Map* new_map;
4460  { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
4461  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4462  }
4463  set_map(new_map);
4464  // When running crankshaft, changing the map is not enough. We
4465  // need to deoptimize all functions that rely on this global
4466  // object.
4468  }
4469 
4470  // Update the dictionary with the new CALLBACKS property.
4471  PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
4472  { MaybeObject* maybe_ok = SetNormalizedProperty(name, structure, details);
4473  if (maybe_ok->IsFailure()) return maybe_ok;
4474  }
4475 
4476  return GetHeap()->undefined_value();
4477 }
4478 
4479 
4481  Handle<String> name,
4482  Handle<Object> getter,
4483  Handle<Object> setter,
4484  PropertyAttributes attributes) {
4486  object->GetIsolate(),
4487  object->DefineAccessor(*name, *getter, *setter, attributes));
4488 }
4489 
4491  Object* getter,
4492  Object* setter,
4493  PropertyAttributes attributes) {
4494  Isolate* isolate = GetIsolate();
4495  // Check access rights if needed.
4496  if (IsAccessCheckNeeded() &&
4497  !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4498  isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4499  return isolate->heap()->undefined_value();
4500  }
4501 
4502  if (IsJSGlobalProxy()) {
4503  Object* proto = GetPrototype();
4504  if (proto->IsNull()) return this;
4505  ASSERT(proto->IsJSGlobalObject());
4506  return JSObject::cast(proto)->DefineAccessor(
4507  name, getter, setter, attributes);
4508  }
4509 
4510  // Make sure that the top context does not change when doing callbacks or
4511  // interceptor calls.
4512  AssertNoContextChange ncc;
4513 
4514  // Try to flatten before operating on the string.
4515  name->TryFlatten();
4516 
4517  if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
4518 
4519  uint32_t index = 0;
4520  return name->AsArrayIndex(&index) ?
4521  DefineElementAccessor(index, getter, setter, attributes) :
4522  DefinePropertyAccessor(name, getter, setter, attributes);
4523 }
4524 
4525 
4526 static MaybeObject* CreateFreshAccessor(JSObject* obj,
4527  String* name,
4528  AccessorComponent component,
4529  Object* accessor,
4530  PropertyAttributes attributes) {
4531  // step 1: create a new getter/setter pair with only the accessor in it
4532  Heap* heap = obj->GetHeap();
4533  AccessorPair* accessors2;
4534  { MaybeObject* maybe_accessors2 = heap->AllocateAccessorPair();
4535  if (!maybe_accessors2->To(&accessors2)) return maybe_accessors2;
4536  }
4537  accessors2->set(component, accessor);
4538 
4539  // step 2: create a copy of the descriptors, incl. the new getter/setter pair
4540  Map* map1 = obj->map();
4541  CallbacksDescriptor callbacks_descr2(name, accessors2, attributes);
4542  DescriptorArray* descriptors2;
4543  { MaybeObject* maybe_descriptors2 =
4544  map1->instance_descriptors()->CopyInsert(&callbacks_descr2,
4546  if (!maybe_descriptors2->To(&descriptors2)) return maybe_descriptors2;
4547  }
4548 
4549  // step 3: create a new map with the new descriptors
4550  Map* map2;
4551  { MaybeObject* maybe_map2 = map1->CopyDropDescriptors();
4552  if (!maybe_map2->To(&map2)) return maybe_map2;
4553  }
4554  map2->set_instance_descriptors(descriptors2);
4555 
4556  // step 4: create a new getter/setter pair with a transition to the new map
4557  AccessorPair* accessors1;
4558  { MaybeObject* maybe_accessors1 = heap->AllocateAccessorPair();
4559  if (!maybe_accessors1->To(&accessors1)) return maybe_accessors1;
4560  }
4561  accessors1->set(component, map2);
4562 
4563  // step 5: create a copy of the descriptors, incl. the new getter/setter pair
4564  // with the transition
4565  CallbacksDescriptor callbacks_descr1(name, accessors1, attributes);
4566  DescriptorArray* descriptors1;
4567  { MaybeObject* maybe_descriptors1 =
4568  map1->instance_descriptors()->CopyInsert(&callbacks_descr1,
4570  if (!maybe_descriptors1->To(&descriptors1)) return maybe_descriptors1;
4571  }
4572 
4573  // step 6: everything went well so far, so we make our changes visible
4574  obj->set_map(map2);
4575  map1->set_instance_descriptors(descriptors1);
4576  map2->SetBackPointer(map1);
4577  return obj;
4578 }
4579 
4580 
4581 static bool TransitionToSameAccessor(Object* map,
4582  String* name,
4583  AccessorComponent component,
4584  Object* accessor,
4585  PropertyAttributes attributes ) {
4586  DescriptorArray* descs = Map::cast(map)->instance_descriptors();
4587  int number = descs->SearchWithCache(name);
4589  Object* target_accessor =
4590  AccessorPair::cast(descs->GetCallbacksObject(number))->get(component);
4591  PropertyAttributes target_attributes = descs->GetDetails(number).attributes();
4592  return target_accessor == accessor && target_attributes == attributes;
4593 }
4594 
4595 
4596 static MaybeObject* NewCallbackTransition(JSObject* obj,
4597  String* name,
4598  AccessorComponent component,
4599  Object* accessor,
4600  PropertyAttributes attributes,
4601  AccessorPair* accessors2) {
4602  // step 1: copy the old getter/setter pair and set the new accessor
4603  AccessorPair* accessors3;
4604  { MaybeObject* maybe_accessors3 = accessors2->CopyWithoutTransitions();
4605  if (!maybe_accessors3->To(&accessors3)) return maybe_accessors3;
4606  }
4607  accessors3->set(component, accessor);
4608 
4609  // step 2: create a copy of the descriptors, incl. the new getter/setter pair
4610  Map* map2 = obj->map();
4611  CallbacksDescriptor callbacks_descr3(name, accessors3, attributes);
4612  DescriptorArray* descriptors3;
4613  { MaybeObject* maybe_descriptors3 =
4614  map2->instance_descriptors()->CopyInsert(&callbacks_descr3,
4616  if (!maybe_descriptors3->To(&descriptors3)) return maybe_descriptors3;
4617  }
4618 
4619  // step 3: create a new map with the new descriptors
4620  Map* map3;
4621  { MaybeObject* maybe_map3 = map2->CopyDropDescriptors();
4622  if (!maybe_map3->To(&map3)) return maybe_map3;
4623  }
4624  map3->set_instance_descriptors(descriptors3);
4625 
4626  // step 4: everything went well so far, so we make our changes visible
4627  obj->set_map(map3);
4628  accessors2->set(component, map3);
4629  map3->SetBackPointer(map2);
4630  return obj;
4631 }
4632 
4633 
4635  AccessorComponent component,
4636  Object* accessor,
4637  PropertyAttributes attributes) {
4638  ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined());
4639  LookupResult result(GetIsolate());
4640  LocalLookup(name, &result);
4641 
4642  // If we have a new property, create a fresh accessor plus a transition to it.
4643  if (!result.IsFound()) {
4644  return CreateFreshAccessor(this, name, component, accessor, attributes);
4645  }
4646 
4647  // If the property is not a JavaScript accessor, fall back to the slow case.
4648  if (result.type() != CALLBACKS) return GetHeap()->null_value();
4649  Object* callback_value = result.GetCallbackObject();
4650  if (!callback_value->IsAccessorPair()) return GetHeap()->null_value();
4651  AccessorPair* accessors = AccessorPair::cast(callback_value);
4652 
4653  // Follow a callback transition, if there is a fitting one.
4654  Object* entry = accessors->get(component);
4655  if (entry->IsMap() &&
4656  TransitionToSameAccessor(entry, name, component, accessor, attributes)) {
4657  set_map(Map::cast(entry));
4658  return this;
4659  }
4660 
4661  // When we re-add the same accessor again, there is nothing to do.
4662  if (entry == accessor && result.GetAttributes() == attributes) return this;
4663 
4664  // Only the other accessor has been set so far, create a new transition.
4665  if (entry->IsTheHole()) {
4666  return NewCallbackTransition(this,
4667  name,
4668  component,
4669  accessor,
4670  attributes,
4671  accessors);
4672  }
4673 
4674  // Nothing from the above worked, so we have to fall back to the slow case.
4675  return GetHeap()->null_value();
4676 }
4677 
4678 
4680  Isolate* isolate = GetIsolate();
4681  String* name = String::cast(info->name());
4682  // Check access rights if needed.
4683  if (IsAccessCheckNeeded() &&
4684  !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4685  isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4686  return isolate->heap()->undefined_value();
4687  }
4688 
4689  if (IsJSGlobalProxy()) {
4690  Object* proto = GetPrototype();
4691  if (proto->IsNull()) return this;
4692  ASSERT(proto->IsJSGlobalObject());
4693  return JSObject::cast(proto)->DefineAccessor(info);
4694  }
4695 
4696  // Make sure that the top context does not change when doing callbacks or
4697  // interceptor calls.
4698  AssertNoContextChange ncc;
4699 
4700  // Try to flatten before operating on the string.
4701  name->TryFlatten();
4702 
4703  if (!CanSetCallback(name)) {
4704  return isolate->heap()->undefined_value();
4705  }
4706 
4707  uint32_t index = 0;
4708  bool is_element = name->AsArrayIndex(&index);
4709 
4710  if (is_element) {
4711  if (IsJSArray()) return isolate->heap()->undefined_value();
4712 
4713  // Accessors overwrite previous callbacks (cf. with getters/setters).
4714  switch (GetElementsKind()) {
4715  case FAST_SMI_ELEMENTS:
4716  case FAST_ELEMENTS:
4717  case FAST_DOUBLE_ELEMENTS:
4719  case FAST_HOLEY_ELEMENTS:
4721  break;
4727  case EXTERNAL_INT_ELEMENTS:
4731  // Ignore getters and setters on pixel and external array
4732  // elements.
4733  return isolate->heap()->undefined_value();
4734  case DICTIONARY_ELEMENTS:
4735  break;
4737  UNIMPLEMENTED();
4738  break;
4739  }
4740 
4741  { MaybeObject* maybe_ok =
4742  SetElementCallback(index, info, info->property_attributes());
4743  if (maybe_ok->IsFailure()) return maybe_ok;
4744  }
4745  } else {
4746  // Lookup the name.
4747  LookupResult result(isolate);
4748  LocalLookup(name, &result);
4749  // ES5 forbids turning a property into an accessor if it's not
4750  // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
4751  if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) {
4752  return isolate->heap()->undefined_value();
4753  }
4754  { MaybeObject* maybe_ok =
4755  SetPropertyCallback(name, info, info->property_attributes());
4756  if (maybe_ok->IsFailure()) return maybe_ok;
4757  }
4758  }
4759 
4760  return this;
4761 }
4762 
4763 
4765  Heap* heap = GetHeap();
4766 
4767  // Make sure that the top context does not change when doing callbacks or
4768  // interceptor calls.
4769  AssertNoContextChange ncc;
4770 
4771  // Check access rights if needed.
4772  if (IsAccessCheckNeeded() &&
4773  !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) {
4775  return heap->undefined_value();
4776  }
4777 
4778  // Make the lookup and include prototypes.
4779  uint32_t index = 0;
4780  if (name->AsArrayIndex(&index)) {
4781  for (Object* obj = this;
4782  obj != heap->null_value();
4783  obj = JSObject::cast(obj)->GetPrototype()) {
4784  JSObject* js_object = JSObject::cast(obj);
4785  if (js_object->HasDictionaryElements()) {
4786  SeededNumberDictionary* dictionary = js_object->element_dictionary();
4787  int entry = dictionary->FindEntry(index);
4788  if (entry != SeededNumberDictionary::kNotFound) {
4789  Object* element = dictionary->ValueAt(entry);
4790  if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
4791  element->IsAccessorPair()) {
4792  return AccessorPair::cast(element)->GetComponent(component);
4793  }
4794  }
4795  }
4796  }
4797  } else {
4798  for (Object* obj = this;
4799  obj != heap->null_value();
4800  obj = JSObject::cast(obj)->GetPrototype()) {
4801  LookupResult result(heap->isolate());
4802  JSObject::cast(obj)->LocalLookup(name, &result);
4803  if (result.IsProperty()) {
4804  if (result.IsReadOnly()) return heap->undefined_value();
4805  if (result.type() == CALLBACKS) {
4806  Object* obj = result.GetCallbackObject();
4807  if (obj->IsAccessorPair()) {
4808  return AccessorPair::cast(obj)->GetComponent(component);
4809  }
4810  }
4811  }
4812  }
4813  }
4814  return heap->undefined_value();
4815 }
4816 
4817 
4819  if (HasFastProperties()) {
4820  DescriptorArray* descs = map()->instance_descriptors();
4821  for (int i = 0; i < descs->number_of_descriptors(); i++) {
4822  if (descs->GetType(i) == FIELD) {
4823  if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
4824  return descs->GetKey(i);
4825  }
4826  } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
4827  if (descs->GetConstantFunction(i) == value) {
4828  return descs->GetKey(i);
4829  }
4830  }
4831  }
4832  return GetHeap()->undefined_value();
4833  } else {
4834  return property_dictionary()->SlowReverseLookup(value);
4835  }
4836 }
4837 
4838 
4840  Heap* heap = GetHeap();
4841  Object* result;
4842  { MaybeObject* maybe_result =
4843  heap->AllocateMap(instance_type(), instance_size());
4844  if (!maybe_result->ToObject(&result)) return maybe_result;
4845  }
4846  Map::cast(result)->set_prototype(prototype());
4847  Map::cast(result)->set_constructor(constructor());
4848  // Don't copy descriptors, so map transitions always remain a forest.
4849  // If we retained the same descriptors we would have two maps
4850  // pointing to the same transition which is bad because the garbage
4851  // collector relies on being able to reverse pointers from transitions
4852  // to maps. If properties need to be retained use CopyDropTransitions.
4854  // Please note instance_type and instance_size are set when allocated.
4855  Map::cast(result)->set_inobject_properties(inobject_properties());
4856  Map::cast(result)->set_unused_property_fields(unused_property_fields());
4857 
4858  // If the map has pre-allocated properties always start out with a descriptor
4859  // array describing these properties.
4860  if (pre_allocated_property_fields() > 0) {
4861  ASSERT(constructor()->IsJSFunction());
4862  JSFunction* ctor = JSFunction::cast(constructor());
4863  Object* descriptors;
4864  { MaybeObject* maybe_descriptors =
4865  ctor->initial_map()->instance_descriptors()->RemoveTransitions(
4867  if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
4868  }
4869  Map::cast(result)->set_instance_descriptors(
4870  DescriptorArray::cast(descriptors));
4872  pre_allocated_property_fields());
4873  }
4874  Map::cast(result)->set_bit_field(bit_field());
4875  Map::cast(result)->set_bit_field2(bit_field2());
4876  Map::cast(result)->set_bit_field3(bit_field3());
4877  Map::cast(result)->set_is_shared(false);
4878  Map::cast(result)->ClearCodeCache(heap);
4879  return result;
4880 }
4881 
4882 
4884  NormalizedMapSharingMode sharing) {
4885  int new_instance_size = instance_size();
4886  if (mode == CLEAR_INOBJECT_PROPERTIES) {
4887  new_instance_size -= inobject_properties() * kPointerSize;
4888  }
4889 
4890  Object* result;
4891  { MaybeObject* maybe_result =
4892  GetHeap()->AllocateMap(instance_type(), new_instance_size);
4893  if (!maybe_result->ToObject(&result)) return maybe_result;
4894  }
4895 
4896  if (mode != CLEAR_INOBJECT_PROPERTIES) {
4897  Map::cast(result)->set_inobject_properties(inobject_properties());
4898  }
4899 
4900  Map::cast(result)->set_prototype(prototype());
4901  Map::cast(result)->set_constructor(constructor());
4902 
4903  Map::cast(result)->set_bit_field(bit_field());
4904  Map::cast(result)->set_bit_field2(bit_field2());
4905  Map::cast(result)->set_bit_field3(bit_field3());
4906  Map::cast(result)->set_code_cache(code_cache());
4907 
4908  Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
4909 
4910 #ifdef DEBUG
4911  if (FLAG_verify_heap && Map::cast(result)->is_shared()) {
4912  Map::cast(result)->SharedMapVerify();
4913  }
4914 #endif
4915 
4916  return result;
4917 }
4918 
4919 
4921  DescriptorArray::SharedMode shared_mode) {
4922  Object* new_map;
4923  { MaybeObject* maybe_new_map = CopyDropDescriptors();
4924  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
4925  }
4926  Object* descriptors;
4927  { MaybeObject* maybe_descriptors =
4928  instance_descriptors()->RemoveTransitions(shared_mode);
4929  if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
4930  }
4931  cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
4932  return new_map;
4933 }
4934 
4935 
4937  Handle<String> name,
4938  Handle<Code> code) {
4939  Isolate* isolate = map->GetIsolate();
4940  CALL_HEAP_FUNCTION_VOID(isolate,
4941  map->UpdateCodeCache(*name, *code));
4942 }
4943 
4944 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) {
4945  ASSERT(!is_shared() || code->allowed_in_shared_map_code_cache());
4946 
4947  // Allocate the code cache if not present.
4948  if (code_cache()->IsFixedArray()) {
4949  Object* result;
4950  { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache();
4951  if (!maybe_result->ToObject(&result)) return maybe_result;
4952  }
4953  set_code_cache(result);
4954  }
4955 
4956  // Update the code cache.
4957  return CodeCache::cast(code_cache())->Update(name, code);
4958 }
4959 
4960 
4962  // Do a lookup if a code cache exists.
4963  if (!code_cache()->IsFixedArray()) {
4964  return CodeCache::cast(code_cache())->Lookup(name, flags);
4965  } else {
4966  return GetHeap()->undefined_value();
4967  }
4968 }
4969 
4970 
4971 int Map::IndexInCodeCache(Object* name, Code* code) {
4972  // Get the internal index if a code cache exists.
4973  if (!code_cache()->IsFixedArray()) {
4974  return CodeCache::cast(code_cache())->GetIndex(name, code);
4975  }
4976  return -1;
4977 }
4978 
4979 
4980 void Map::RemoveFromCodeCache(String* name, Code* code, int index) {
4981  // No GC is supposed to happen between a call to IndexInCodeCache and
4982  // RemoveFromCodeCache so the code cache must be there.
4983  ASSERT(!code_cache()->IsFixedArray());
4984  CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
4985 }
4986 
4987 
4988 // An iterator over all map transitions in an descriptor array, reusing the map
4989 // field of the contens array while it is running.
4991  public:
4993  : descriptor_array_(descriptor_array) { }
4994 
4995  void Start() {
4996  ASSERT(!IsIterating());
4997  if (descriptor_array_->MayContainTransitions())
4998  *DescriptorArrayHeader() = Smi::FromInt(0);
4999  }
5000 
5001  bool IsIterating() {
5002  return descriptor_array_->MayContainTransitions() &&
5003  (*DescriptorArrayHeader())->IsSmi();
5004  }
5005 
5006  Map* Next() {
5007  ASSERT(IsIterating());
5008  // Attention, tricky index manipulation ahead: Two consecutive indices are
5009  // assigned to each descriptor. Most descriptors directly advance to the
5010  // next descriptor by adding 2 to the index. The exceptions are the
5011  // CALLBACKS entries: An even index means we look at its getter, and an odd
5012  // index means we look at its setter.
5013  int raw_index = Smi::cast(*DescriptorArrayHeader())->value();
5014  int index = raw_index / 2;
5015  int number_of_descriptors = descriptor_array_->number_of_descriptors();
5016  while (index < number_of_descriptors) {
5017  PropertyDetails details(descriptor_array_->GetDetails(index));
5018  switch (details.type()) {
5019  case MAP_TRANSITION:
5020  case CONSTANT_TRANSITION:
5021  // We definitely have a map transition.
5022  *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2);
5023  return static_cast<Map*>(descriptor_array_->GetValue(index));
5024  case CALLBACKS: {
5025  // We might have a map transition in a getter or in a setter.
5026  AccessorPair* accessors =
5027  static_cast<AccessorPair*>(descriptor_array_->GetValue(index));
5028  Object* accessor;
5029  if ((raw_index & 1) == 0) {
5030  accessor = accessors->setter();
5031  } else {
5032  ++index;
5033  accessor = accessors->getter();
5034  }
5035  ++raw_index;
5036  if (accessor->IsMap()) {
5037  *DescriptorArrayHeader() = Smi::FromInt(raw_index);
5038  return static_cast<Map*>(accessor);
5039  }
5040  break;
5041  }
5042  case NORMAL:
5043  case FIELD:
5044  case CONSTANT_FUNCTION:
5045  case HANDLER:
5046  case INTERCEPTOR:
5047  case NULL_DESCRIPTOR:
5048  // We definitely have no map transition.
5049  raw_index += 2;
5050  ++index;
5051  break;
5052  }
5053  }
5054  if (index == descriptor_array_->number_of_descriptors()) {
5055  Map* elements_transition = descriptor_array_->elements_transition_map();
5056  if (elements_transition != NULL) {
5057  *DescriptorArrayHeader() = Smi::FromInt(index + 1);
5058  return elements_transition;
5059  }
5060  }
5061  *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map();
5062  return NULL;
5063  }
5064 
5065  private:
5066  Object** DescriptorArrayHeader() {
5067  return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset);
5068  }
5069 
5070  DescriptorArray* descriptor_array_;
5071 };
5072 
5073 
5074 // An iterator over all prototype transitions, reusing the map field of the
5075 // underlying array while it is running.
5077  public:
5079  : proto_trans_(proto_trans) { }
5080 
5081  void Start() {
5082  ASSERT(!IsIterating());
5083  if (HasTransitions()) *Header() = Smi::FromInt(0);
5084  }
5085 
5086  bool IsIterating() {
5087  return HasTransitions() && (*Header())->IsSmi();
5088  }
5089 
5090  Map* Next() {
5091  ASSERT(IsIterating());
5092  int transitionNumber = Smi::cast(*Header())->value();
5093  if (transitionNumber < NumberOfTransitions()) {
5094  *Header() = Smi::FromInt(transitionNumber + 1);
5095  return GetTransition(transitionNumber);
5096  }
5097  *Header() = proto_trans_->GetHeap()->fixed_array_map();
5098  return NULL;
5099  }
5100 
5101  private:
5102  bool HasTransitions() {
5103  return proto_trans_->map()->IsSmi() || proto_trans_->IsFixedArray();
5104  }
5105 
5106  Object** Header() {
5107  return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset);
5108  }
5109 
5110  int NumberOfTransitions() {
5111  ASSERT(HasTransitions());
5112  FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
5113  Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
5114  return Smi::cast(num)->value();
5115  }
5116 
5117  Map* GetTransition(int transitionNumber) {
5118  ASSERT(HasTransitions());
5119  FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
5120  return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
5121  }
5122 
5123  int IndexFor(int transitionNumber) {
5126  transitionNumber * Map::kProtoTransitionElementsPerEntry;
5127  }
5128 
5129  HeapObject* proto_trans_;
5130 };
5131 
5132 
5133 // To traverse the transition tree iteratively, we have to store two kinds of
5134 // information in a map: The parent map in the traversal and which children of a
5135 // node have already been visited. To do this without additional memory, we
5136 // temporarily reuse two maps with known values:
5137 //
5138 // (1) The map of the map temporarily holds the parent, and is restored to the
5139 // meta map afterwards.
5140 //
5141 // (2) The info which children have already been visited depends on which part
5142 // of the map we currently iterate:
5143 //
5144 // (a) If we currently follow normal map transitions, we temporarily store
5145 // the current index in the map of the FixedArray of the desciptor
5146 // array's contents, and restore it to the fixed array map afterwards.
5147 // Note that a single descriptor can have 0, 1, or 2 transitions.
5148 //
5149 // (b) If we currently follow prototype transitions, we temporarily store
5150 // the current index in the map of the FixedArray holding the prototype
5151 // transitions, and restore it to the fixed array map afterwards.
5152 //
5153 // Note that the child iterator is just a concatenation of two iterators: One
5154 // iterating over map transitions and one iterating over prototype transisitons.
5155 class TraversableMap : public Map {
5156  public:
5157  // Record the parent in the traversal within this map. Note that this destroys
5158  // this map's map!
5160 
5161  // Reset the current map's map, returning the parent previously stored in it.
5163  TraversableMap* old_parent = static_cast<TraversableMap*>(map());
5164  set_map_no_write_barrier(GetHeap()->meta_map());
5165  return old_parent;
5166  }
5167 
5168  // Can either be Smi (no instance descriptors), or a descriptor array with the
5169  // header overwritten as a Smi (thus iterating).
5171  Object* object =
5172  *HeapObject::RawField(this, kInstanceDescriptorsOrBitField3Offset);
5173  if (object->IsSmi()) {
5174  return GetHeap()->empty_descriptor_array();
5175  } else {
5176  DescriptorArray* descriptor_array =
5177  static_cast<DescriptorArray*>(object);
5178  return descriptor_array;
5179  }
5180  }
5181 
5182  // Start iterating over this map's children, possibly destroying a FixedArray
5183  // map (see explanation above).
5185  IntrusiveMapTransitionIterator(instance_descriptors()).Start();
5187  unchecked_prototype_transitions()).Start();
5188  }
5189 
5190  // If we have an unvisited child map, return that one and advance. If we have
5191  // none, return NULL and reset any destroyed FixedArray maps.
5194  proto_iterator(unchecked_prototype_transitions());
5195  if (proto_iterator.IsIterating()) {
5196  Map* next = proto_iterator.Next();
5197  if (next != NULL) return static_cast<TraversableMap*>(next);
5198  }
5200  descriptor_iterator(MutatedInstanceDescriptors());
5201  if (descriptor_iterator.IsIterating()) {
5202  Map* next = descriptor_iterator.Next();
5203  if (next != NULL) return static_cast<TraversableMap*>(next);
5204  }
5205  return NULL;
5206  }
5207 };
5208 
5209 
5210 // Traverse the transition tree in postorder without using the C++ stack by
5211 // doing pointer reversal.
5212 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
5213  TraversableMap* current = static_cast<TraversableMap*>(this);
5214  current->ChildIteratorStart();
5215  while (true) {
5216  TraversableMap* child = current->ChildIteratorNext();
5217  if (child != NULL) {
5218  child->ChildIteratorStart();
5219  child->SetParent(current);
5220  current = child;
5221  } else {
5222  TraversableMap* parent = current->GetAndResetParent();
5223  callback(current, data);
5224  if (current == this) break;
5225  current = parent;
5226  }
5227  }
5228 }
5229 
5230 
5231 MaybeObject* CodeCache::Update(String* name, Code* code) {
5232  // The number of monomorphic stubs for normal load/store/call IC's can grow to
5233  // a large number and therefore they need to go into a hash table. They are
5234  // used to load global properties from cells.
5235  if (code->type() == NORMAL) {
5236  // Make sure that a hash table is allocated for the normal load code cache.
5237  if (normal_type_cache()->IsUndefined()) {
5238  Object* result;
5239  { MaybeObject* maybe_result =
5241  if (!maybe_result->ToObject(&result)) return maybe_result;
5242  }
5243  set_normal_type_cache(result);
5244  }
5245  return UpdateNormalTypeCache(name, code);
5246  } else {
5247  ASSERT(default_cache()->IsFixedArray());
5248  return UpdateDefaultCache(name, code);
5249  }
5250 }
5251 
5252 
5253 MaybeObject* CodeCache::UpdateDefaultCache(String* name, Code* code) {
5254  // When updating the default code cache we disregard the type encoded in the
5255  // flags. This allows call constant stubs to overwrite call field
5256  // stubs, etc.
5258 
5259  // First check whether we can update existing code cache without
5260  // extending it.
5261  FixedArray* cache = default_cache();
5262  int length = cache->length();
5263  int deleted_index = -1;
5264  for (int i = 0; i < length; i += kCodeCacheEntrySize) {
5265  Object* key = cache->get(i);
5266  if (key->IsNull()) {
5267  if (deleted_index < 0) deleted_index = i;
5268  continue;
5269  }
5270  if (key->IsUndefined()) {
5271  if (deleted_index >= 0) i = deleted_index;
5272  cache->set(i + kCodeCacheEntryNameOffset, name);
5273  cache->set(i + kCodeCacheEntryCodeOffset, code);
5274  return this;
5275  }
5276  if (name->Equals(String::cast(key))) {
5277  Code::Flags found =
5278  Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
5279  if (Code::RemoveTypeFromFlags(found) == flags) {
5280  cache->set(i + kCodeCacheEntryCodeOffset, code);
5281  return this;
5282  }
5283  }
5284  }
5285 
5286  // Reached the end of the code cache. If there were deleted
5287  // elements, reuse the space for the first of them.
5288  if (deleted_index >= 0) {
5289  cache->set(deleted_index + kCodeCacheEntryNameOffset, name);
5290  cache->set(deleted_index + kCodeCacheEntryCodeOffset, code);
5291  return this;
5292  }
5293 
5294  // Extend the code cache with some new entries (at least one). Must be a
5295  // multiple of the entry size.
5296  int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
5297  new_length = new_length - new_length % kCodeCacheEntrySize;
5298  ASSERT((new_length % kCodeCacheEntrySize) == 0);
5299  Object* result;
5300  { MaybeObject* maybe_result = cache->CopySize(new_length);
5301  if (!maybe_result->ToObject(&result)) return maybe_result;
5302  }
5303 
5304  // Add the (name, code) pair to the new cache.
5305  cache = FixedArray::cast(result);
5306  cache->set(length + kCodeCacheEntryNameOffset, name);
5307  cache->set(length + kCodeCacheEntryCodeOffset, code);
5308  set_default_cache(cache);
5309  return this;
5310 }
5311 
5312 
5313 MaybeObject* CodeCache::UpdateNormalTypeCache(String* name, Code* code) {
5314  // Adding a new entry can cause a new cache to be allocated.
5315  CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5316  Object* new_cache;
5317  { MaybeObject* maybe_new_cache = cache->Put(name, code);
5318  if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
5319  }
5320  set_normal_type_cache(new_cache);
5321  return this;
5322 }
5323 
5324 
5326  if (Code::ExtractTypeFromFlags(flags) == NORMAL) {
5327  return LookupNormalTypeCache(name, flags);
5328  } else {
5329  return LookupDefaultCache(name, flags);
5330  }
5331 }
5332 
5333 
5334 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) {
5335  FixedArray* cache = default_cache();
5336  int length = cache->length();
5337  for (int i = 0; i < length; i += kCodeCacheEntrySize) {
5338  Object* key = cache->get(i + kCodeCacheEntryNameOffset);
5339  // Skip deleted elements.
5340  if (key->IsNull()) continue;
5341  if (key->IsUndefined()) return key;
5342  if (name->Equals(String::cast(key))) {
5343  Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
5344  if (code->flags() == flags) {
5345  return code;
5346  }
5347  }
5348  }
5349  return GetHeap()->undefined_value();
5350 }
5351 
5352 
5353 Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) {
5354  if (!normal_type_cache()->IsUndefined()) {
5355  CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5356  return cache->Lookup(name, flags);
5357  } else {
5358  return GetHeap()->undefined_value();
5359  }
5360 }
5361 
5362 
5363 int CodeCache::GetIndex(Object* name, Code* code) {
5364  if (code->type() == NORMAL) {
5365  if (normal_type_cache()->IsUndefined()) return -1;
5366  CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5367  return cache->GetIndex(String::cast(name), code->flags());
5368  }
5369 
5370  FixedArray* array = default_cache();
5371  int len = array->length();
5372  for (int i = 0; i < len; i += kCodeCacheEntrySize) {
5373  if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
5374  }
5375  return -1;
5376 }
5377 
5378 
5379 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
5380  if (code->type() == NORMAL) {
5381  ASSERT(!normal_type_cache()->IsUndefined());
5382  CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5383  ASSERT(cache->GetIndex(String::cast(name), code->flags()) == index);
5384  cache->RemoveByIndex(index);
5385  } else {
5386  FixedArray* array = default_cache();
5387  ASSERT(array->length() >= index && array->get(index)->IsCode());
5388  // Use null instead of undefined for deleted elements to distinguish
5389  // deleted elements from unused elements. This distinction is used
5390  // when looking up in the cache and when updating the cache.
5391  ASSERT_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
5392  array->set_null(index - 1); // Name.
5393  array->set_null(index); // Code.
5394  }
5395 }
5396 
5397 
5398 // The key in the code cache hash table consists of the property name and the
5399 // code object. The actual match is on the name and the code flags. If a key
5400 // is created using the flags and not a code object it can only be used for
5401 // lookup not to create a new entry.
5403  public:
5405  : name_(name), flags_(flags), code_(NULL) { }
5406 
5408  : name_(name),
5409  flags_(code->flags()),
5410  code_(code) { }
5411 
5412 
5413  bool IsMatch(Object* other) {
5414  if (!other->IsFixedArray()) return false;
5415  FixedArray* pair = FixedArray::cast(other);
5416  String* name = String::cast(pair->get(0));
5417  Code::Flags flags = Code::cast(pair->get(1))->flags();
5418  if (flags != flags_) {
5419  return false;
5420  }
5421  return name_->Equals(name);
5422  }
5423 
5424  static uint32_t NameFlagsHashHelper(String* name, Code::Flags flags) {
5425  return name->Hash() ^ flags;
5426  }
5427 
5428  uint32_t Hash() { return NameFlagsHashHelper(name_, flags_); }
5429 
5430  uint32_t HashForObject(Object* obj) {
5431  FixedArray* pair = FixedArray::cast(obj);
5432  String* name = String::cast(pair->get(0));
5433  Code* code = Code::cast(pair->get(1));
5434  return NameFlagsHashHelper(name, code->flags());
5435  }
5436 
5437  MUST_USE_RESULT MaybeObject* AsObject() {
5438  ASSERT(code_ != NULL);
5439  Object* obj;
5440  { MaybeObject* maybe_obj = code_->GetHeap()->AllocateFixedArray(2);
5441  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5442  }
5443  FixedArray* pair = FixedArray::cast(obj);
5444  pair->set(0, name_);
5445  pair->set(1, code_);
5446  return pair;
5447  }
5448 
5449  private:
5450  String* name_;
5451  Code::Flags flags_;
5452  // TODO(jkummerow): We should be able to get by without this.
5453  Code* code_;
5454 };
5455 
5456 
5458  CodeCacheHashTableKey key(name, flags);
5459  int entry = FindEntry(&key);
5460  if (entry == kNotFound) return GetHeap()->undefined_value();
5461  return get(EntryToIndex(entry) + 1);
5462 }
5463 
5464 
5465 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) {
5466  CodeCacheHashTableKey key(name, code);
5467  Object* obj;
5468  { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
5469  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5470  }
5471 
5472  // Don't use |this|, as the table might have grown.
5473  CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj);
5474 
5475  int entry = cache->FindInsertionEntry(key.Hash());
5476  Object* k;
5477  { MaybeObject* maybe_k = key.AsObject();
5478  if (!maybe_k->ToObject(&k)) return maybe_k;
5479  }
5480 
5481  cache->set(EntryToIndex(entry), k);
5482  cache->set(EntryToIndex(entry) + 1, code);
5483  cache->ElementAdded();
5484  return cache;
5485 }
5486 
5487 
5489  CodeCacheHashTableKey key(name, flags);
5490  int entry = FindEntry(&key);
5491  return (entry == kNotFound) ? -1 : entry;
5492 }
5493 
5494 
5496  ASSERT(index >= 0);
5497  Heap* heap = GetHeap();
5498  set(EntryToIndex(index), heap->the_hole_value());
5499  set(EntryToIndex(index) + 1, heap->the_hole_value());
5500  ElementRemoved();
5501 }
5502 
5503 
5505  MapHandleList* maps,
5506  Code::Flags flags,
5507  Handle<Code> code) {
5508  Isolate* isolate = cache->GetIsolate();
5509  CALL_HEAP_FUNCTION_VOID(isolate, cache->Update(maps, flags, *code));
5510 }
5511 
5512 
5514  Code::Flags flags,
5515  Code* code) {
5516  // Initialize cache if necessary.
5517  if (cache()->IsUndefined()) {
5518  Object* result;
5519  { MaybeObject* maybe_result =
5522  if (!maybe_result->ToObject(&result)) return maybe_result;
5523  }
5524  set_cache(result);
5525  } else {
5526  // This entry shouldn't be contained in the cache yet.
5528  ->Lookup(maps, flags)->IsUndefined());
5529  }
5530  PolymorphicCodeCacheHashTable* hash_table =
5532  Object* new_cache;
5533  { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code);
5534  if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
5535  }
5536  set_cache(new_cache);
5537  return this;
5538 }
5539 
5540 
5542  Code::Flags flags) {
5543  if (!cache()->IsUndefined()) {
5544  PolymorphicCodeCacheHashTable* hash_table =
5546  return Handle<Object>(hash_table->Lookup(maps, flags));
5547  } else {
5548  return GetIsolate()->factory()->undefined_value();
5549  }
5550 }
5551 
5552 
5553 // Despite their name, object of this class are not stored in the actual
5554 // hash table; instead they're temporarily used for lookups. It is therefore
5555 // safe to have a weak (non-owning) pointer to a MapList as a member field.
5557  public:
5558  // Callers must ensure that |maps| outlives the newly constructed object.
5560  : maps_(maps),
5561  code_flags_(code_flags) {}
5562 
5563  bool IsMatch(Object* other) {
5564  MapHandleList other_maps(kDefaultListAllocationSize);
5565  int other_flags;
5566  FromObject(other, &other_flags, &other_maps);
5567  if (code_flags_ != other_flags) return false;
5568  if (maps_->length() != other_maps.length()) return false;
5569  // Compare just the hashes first because it's faster.
5570  int this_hash = MapsHashHelper(maps_, code_flags_);
5571  int other_hash = MapsHashHelper(&other_maps, other_flags);
5572  if (this_hash != other_hash) return false;
5573 
5574  // Full comparison: for each map in maps_, look for an equivalent map in
5575  // other_maps. This implementation is slow, but probably good enough for
5576  // now because the lists are short (<= 4 elements currently).
5577  for (int i = 0; i < maps_->length(); ++i) {
5578  bool match_found = false;
5579  for (int j = 0; j < other_maps.length(); ++j) {
5580  if (*(maps_->at(i)) == *(other_maps.at(j))) {
5581  match_found = true;
5582  break;
5583  }
5584  }
5585  if (!match_found) return false;
5586  }
5587  return true;
5588  }
5589 
5590  static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
5591  uint32_t hash = code_flags;
5592  for (int i = 0; i < maps->length(); ++i) {
5593  hash ^= maps->at(i)->Hash();
5594  }
5595  return hash;
5596  }
5597 
5598  uint32_t Hash() {
5599  return MapsHashHelper(maps_, code_flags_);
5600  }
5601 
5602  uint32_t HashForObject(Object* obj) {
5603  MapHandleList other_maps(kDefaultListAllocationSize);
5604  int other_flags;
5605  FromObject(obj, &other_flags, &other_maps);
5606  return MapsHashHelper(&other_maps, other_flags);
5607  }
5608 
5609  MUST_USE_RESULT MaybeObject* AsObject() {
5610  Object* obj;
5611  // The maps in |maps_| must be copied to a newly allocated FixedArray,
5612  // both because the referenced MapList is short-lived, and because C++
5613  // objects can't be stored in the heap anyway.
5614  { MaybeObject* maybe_obj =
5615  HEAP->AllocateUninitializedFixedArray(maps_->length() + 1);
5616  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5617  }
5618  FixedArray* list = FixedArray::cast(obj);
5619  list->set(0, Smi::FromInt(code_flags_));
5620  for (int i = 0; i < maps_->length(); ++i) {
5621  list->set(i + 1, *maps_->at(i));
5622  }
5623  return list;
5624  }
5625 
5626  private:
5627  static MapHandleList* FromObject(Object* obj,
5628  int* code_flags,
5629  MapHandleList* maps) {
5630  FixedArray* list = FixedArray::cast(obj);
5631  maps->Rewind(0);
5632  *code_flags = Smi::cast(list->get(0))->value();
5633  for (int i = 1; i < list->length(); ++i) {
5634  maps->Add(Handle<Map>(Map::cast(list->get(i))));
5635  }
5636  return maps;
5637  }
5638 
5639  MapHandleList* maps_; // weak.
5640  int code_flags_;
5641  static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
5642 };
5643 
5644 
5646  int code_flags) {
5647  PolymorphicCodeCacheHashTableKey key(maps, code_flags);
5648  int entry = FindEntry(&key);
5649  if (entry == kNotFound) return GetHeap()->undefined_value();
5650  return get(EntryToIndex(entry) + 1);
5651 }
5652 
5653 
5655  int code_flags,
5656  Code* code) {
5657  PolymorphicCodeCacheHashTableKey key(maps, code_flags);
5658  Object* obj;
5659  { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
5660  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5661  }
5663  reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj);
5664  int entry = cache->FindInsertionEntry(key.Hash());
5665  { MaybeObject* maybe_obj = key.AsObject();
5666  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5667  }
5668  cache->set(EntryToIndex(entry), obj);
5669  cache->set(EntryToIndex(entry) + 1, code);
5670  cache->ElementAdded();
5671  return cache;
5672 }
5673 
5674 
5676  ElementsAccessor* accessor = array->GetElementsAccessor();
5677  MaybeObject* maybe_result =
5678  accessor->AddElementsToFixedArray(array, array, this);
5679  FixedArray* result;
5680  if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
5681 #ifdef DEBUG
5683  for (int i = 0; i < result->length(); i++) {
5684  Object* current = result->get(i);
5685  ASSERT(current->IsNumber() || current->IsString());
5686  }
5687  }
5688 #endif
5689  return result;
5690 }
5691 
5692 
5693 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
5694  ElementsAccessor* accessor = ElementsAccessor::ForArray(other);
5695  MaybeObject* maybe_result =
5696  accessor->AddElementsToFixedArray(NULL, NULL, this, other);
5697  FixedArray* result;
5698  if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
5699 #ifdef DEBUG
5701  for (int i = 0; i < result->length(); i++) {
5702  Object* current = result->get(i);
5703  ASSERT(current->IsNumber() || current->IsString());
5704  }
5705  }
5706 #endif
5707  return result;
5708 }
5709 
5710 
5711 MaybeObject* FixedArray::CopySize(int new_length) {
5712  Heap* heap = GetHeap();
5713  if (new_length == 0) return heap->empty_fixed_array();
5714  Object* obj;
5715  { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length);
5716  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5717  }
5718  FixedArray* result = FixedArray::cast(obj);
5719  // Copy the content
5720  AssertNoAllocation no_gc;
5721  int len = length();
5722  if (new_length < len) len = new_length;
5723  // We are taking the map from the old fixed array so the map is sure to
5724  // be an immortal immutable object.
5725  result->set_map_no_write_barrier(map());
5726  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
5727  for (int i = 0; i < len; i++) {
5728  result->set(i, get(i), mode);
5729  }
5730  return result;
5731 }
5732 
5733 
5734 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
5735  AssertNoAllocation no_gc;
5736  WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
5737  for (int index = 0; index < len; index++) {
5738  dest->set(dest_pos+index, get(pos+index), mode);
5739  }
5740 }
5741 
5742 
5743 #ifdef DEBUG
5744 bool FixedArray::IsEqualTo(FixedArray* other) {
5745  if (length() != other->length()) return false;
5746  for (int i = 0 ; i < length(); ++i) {
5747  if (get(i) != other->get(i)) return false;
5748  }
5749  return true;
5750 }
5751 #endif
5752 
5753 
5754 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors,
5755  SharedMode shared_mode) {
5756  Heap* heap = Isolate::Current()->heap();
5757  // Do not use DescriptorArray::cast on incomplete object.
5758  FixedArray* result;
5759  if (number_of_descriptors == 0) {
5760  if (shared_mode == MAY_BE_SHARED) {
5761  return heap->empty_descriptor_array();
5762  }
5763  { MaybeObject* maybe_array =
5764  heap->AllocateFixedArray(kTransitionsIndex + 1);
5765  if (!maybe_array->To(&result)) return maybe_array;
5766  }
5767  } else {
5768  // Allocate the array of keys.
5769  { MaybeObject* maybe_array =
5770  heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors));
5771  if (!maybe_array->To(&result)) return maybe_array;
5772  }
5773  result->set(kEnumerationIndexIndex,
5774  Smi::FromInt(PropertyDetails::kInitialIndex));
5775  }
5776  result->set(kBitField3StorageIndex, Smi::FromInt(0));
5777  result->set(kTransitionsIndex, Smi::FromInt(0));
5778  return result;
5779 }
5780 
5781 
5783  FixedArray* new_cache,
5784  Object* new_index_cache) {
5785  ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
5786  ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
5787  if (HasEnumCache()) {
5788  FixedArray::cast(get(kEnumerationIndexIndex))->
5789  set(kEnumCacheBridgeCacheIndex, new_cache);
5790  FixedArray::cast(get(kEnumerationIndexIndex))->
5791  set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
5792  } else {
5793  if (IsEmpty()) return; // Do nothing for empty descriptor array.
5794  FixedArray::cast(bridge_storage)->
5795  set(kEnumCacheBridgeCacheIndex, new_cache);
5796  FixedArray::cast(bridge_storage)->
5797  set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
5798  NoWriteBarrierSet(FixedArray::cast(bridge_storage),
5799  kEnumCacheBridgeEnumIndex,
5800  get(kEnumerationIndexIndex));
5801  set(kEnumerationIndexIndex, bridge_storage);
5802  }
5803 }
5804 
5805 
5806 static bool InsertionPointFound(String* key1, String* key2) {
5807  return key1->Hash() > key2->Hash() || key1 == key2;
5808 }
5809 
5810 
5812  int dst_index,
5814  int src_index,
5815  const WhitenessWitness& witness) {
5816  CALL_HEAP_FUNCTION_VOID(dst->GetIsolate(),
5817  dst->CopyFrom(dst_index, *src, src_index, witness));
5818 }
5819 
5820 
5821 MaybeObject* DescriptorArray::CopyFrom(int dst_index,
5822  DescriptorArray* src,
5823  int src_index,
5824  const WhitenessWitness& witness) {
5825  Object* value = src->GetValue(src_index);
5826  PropertyDetails details = src->GetDetails(src_index);
5827  if (details.type() == CALLBACKS && value->IsAccessorPair()) {
5828  MaybeObject* maybe_copy =
5830  if (!maybe_copy->To(&value)) return maybe_copy;
5831  }
5832  Descriptor desc(src->GetKey(src_index), value, details);
5833  Set(dst_index, &desc, witness);
5834  return this;
5835 }
5836 
5837 
5838 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor,
5839  TransitionFlag transition_flag) {
5840  // Transitions are only kept when inserting another transition.
5841  // This precondition is not required by this function's implementation, but
5842  // is currently required by the semantics of maps, so we check it.
5843  // Conversely, we filter after replacing, so replacing a transition and
5844  // removing all other transitions is not supported.
5845  bool remove_transitions = transition_flag == REMOVE_TRANSITIONS;
5846  ASSERT(remove_transitions == !descriptor->ContainsTransition());
5847  ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR);
5848 
5849  // Ensure the key is a symbol.
5850  { MaybeObject* maybe_result = descriptor->KeyToSymbol();
5851  if (maybe_result->IsFailure()) return maybe_result;
5852  }
5853 
5854  int new_size = 0;
5855  for (int i = 0; i < number_of_descriptors(); i++) {
5856  if (IsNullDescriptor(i)) continue;
5857  if (remove_transitions && IsTransitionOnly(i)) continue;
5858  new_size++;
5859  }
5860 
5861  // If key is in descriptor, we replace it in-place when filtering.
5862  // Count a null descriptor for key as inserted, not replaced.
5863  int index = Search(descriptor->GetKey());
5864  const bool replacing = (index != kNotFound);
5865  bool keep_enumeration_index = false;
5866  if (!replacing) {
5867  ++new_size;
5868  } else if (!IsTransitionOnly(index)) {
5869  // We are replacing an existing descriptor. We keep the enumeration index
5870  // of a visible property.
5871  keep_enumeration_index = true;
5872  } else if (remove_transitions) {
5873  // Replaced descriptor has been counted as removed if it is a transition
5874  // that will be replaced. Adjust count in this case.
5875  ++new_size;
5876  }
5877 
5878  DescriptorArray* new_descriptors;
5879  { SharedMode mode = remove_transitions ? MAY_BE_SHARED : CANNOT_BE_SHARED;
5880  MaybeObject* maybe_result = Allocate(new_size, mode);
5881  if (!maybe_result->To(&new_descriptors)) return maybe_result;
5882  }
5883 
5884  DescriptorArray::WhitenessWitness witness(new_descriptors);
5885 
5886  // Set the enumeration index in the descriptors and set the enumeration index
5887  // in the result.
5888  int enumeration_index = NextEnumerationIndex();
5889  if (!descriptor->ContainsTransition()) {
5890  if (keep_enumeration_index) {
5891  descriptor->SetEnumerationIndex(GetDetails(index).index());
5892  } else {
5893  descriptor->SetEnumerationIndex(enumeration_index);
5894  ++enumeration_index;
5895  }
5896  }
5897  Map* old_elements_transition = elements_transition_map();
5898  if ((!remove_transitions) && (old_elements_transition != NULL)) {
5899  new_descriptors->set_elements_transition_map(old_elements_transition);
5900  }
5901  new_descriptors->SetNextEnumerationIndex(enumeration_index);
5902 
5903  // Copy the descriptors, filtering out transitions and null descriptors,
5904  // and inserting or replacing a descriptor.
5905  int to_index = 0;
5906  int insertion_index = -1;
5907  int from_index = 0;
5908  while (from_index < number_of_descriptors()) {
5909  if (insertion_index < 0 &&
5910  InsertionPointFound(GetKey(from_index), descriptor->GetKey())) {
5911  insertion_index = to_index++;
5912  if (replacing) from_index++;
5913  } else {
5914  if (!(IsNullDescriptor(from_index) ||
5915  (remove_transitions && IsTransitionOnly(from_index)))) {
5916  MaybeObject* copy_result =
5917  new_descriptors->CopyFrom(to_index++, this, from_index, witness);
5918  if (copy_result->IsFailure()) return copy_result;
5919  }
5920  from_index++;
5921  }
5922  }
5923  if (insertion_index < 0) insertion_index = to_index++;
5924 
5925  ASSERT(insertion_index < new_descriptors->number_of_descriptors());
5926  new_descriptors->Set(insertion_index, descriptor, witness);
5927 
5928  ASSERT(to_index == new_descriptors->number_of_descriptors());
5929  SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
5930 
5931  return new_descriptors;
5932 }
5933 
5934 
5936  // Allocate the new descriptor array.
5937  int new_number_of_descriptors = 0;
5938  for (int i = 0; i < number_of_descriptors(); i++) {
5939  if (IsProperty(i)) new_number_of_descriptors++;
5940  }
5941  DescriptorArray* new_descriptors;
5942  { MaybeObject* maybe_result = Allocate(new_number_of_descriptors,
5943  shared_mode);
5944  if (!maybe_result->To(&new_descriptors)) return maybe_result;
5945  }
5946 
5947  // Copy the content.
5948  DescriptorArray::WhitenessWitness witness(new_descriptors);
5949  int next_descriptor = 0;
5950  for (int i = 0; i < number_of_descriptors(); i++) {
5951  if (IsProperty(i)) {
5952  MaybeObject* copy_result =
5953  new_descriptors->CopyFrom(next_descriptor++, this, i, witness);
5954  if (copy_result->IsFailure()) return copy_result;
5955  }
5956  }
5957  ASSERT(next_descriptor == new_descriptors->number_of_descriptors());
5958  new_descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
5959 
5960  return new_descriptors;
5961 }
5962 
5963 // We need the whiteness witness since sort will reshuffle the entries in the
5964 // descriptor array. If the descriptor array were to be black, the shuffling
5965 // would move a slot that was already recorded as pointing into an evacuation
5966 // candidate. This would result in missing updates upon evacuation.
5968  // In-place heap sort.
5969  int len = number_of_descriptors();
5970 
5971  // Bottom-up max-heap construction.
5972  // Index of the last node with children
5973  const int max_parent_index = (len / 2) - 1;
5974  for (int i = max_parent_index; i >= 0; --i) {
5975  int parent_index = i;
5976  const uint32_t parent_hash = GetKey(i)->Hash();
5977  while (parent_index <= max_parent_index) {
5978  int child_index = 2 * parent_index + 1;
5979  uint32_t child_hash = GetKey(child_index)->Hash();
5980  if (child_index + 1 < len) {
5981  uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
5982  if (right_child_hash > child_hash) {
5983  child_index++;
5984  child_hash = right_child_hash;
5985  }
5986  }
5987  if (child_hash <= parent_hash) break;
5988  NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
5989  // Now element at child_index could be < its children.
5990  parent_index = child_index; // parent_hash remains correct.
5991  }
5992  }
5993 
5994  // Extract elements and create sorted array.
5995  for (int i = len - 1; i > 0; --i) {
5996  // Put max element at the back of the array.
5997  NoIncrementalWriteBarrierSwapDescriptors(0, i);
5998  // Shift down the new top element.
5999  int parent_index = 0;
6000  const uint32_t parent_hash = GetKey(parent_index)->Hash();
6001  const int max_parent_index = (i / 2) - 1;
6002  while (parent_index <= max_parent_index) {
6003  int child_index = parent_index * 2 + 1;
6004  uint32_t child_hash = GetKey(child_index)->Hash();
6005  if (child_index + 1 < i) {
6006  uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
6007  if (right_child_hash > child_hash) {
6008  child_index++;
6009  child_hash = right_child_hash;
6010  }
6011  }
6012  if (child_hash <= parent_hash) break;
6013  NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
6014  parent_index = child_index;
6015  }
6016  }
6017 }
6018 
6019 
6021  SortUnchecked(witness);
6022  SLOW_ASSERT(IsSortedNoDuplicates());
6023 }
6024 
6025 
6026 int DescriptorArray::BinarySearch(String* name, int low, int high) {
6027  uint32_t hash = name->Hash();
6028  int limit = high;
6029 
6030  ASSERT(low <= high);
6031 
6032  while (low != high) {
6033  int mid = (low + high) / 2;
6034  String* mid_name = GetKey(mid);
6035  uint32_t mid_hash = mid_name->Hash();
6036 
6037  if (mid_hash >= hash) {
6038  high = mid;
6039  } else {
6040  low = mid + 1;
6041  }
6042  }
6043 
6044  for (; low <= limit && GetKey(low)->Hash() == hash; ++low) {
6045  if (GetKey(low)->Equals(name) && !IsNullDescriptor(low))
6046  return low;
6047  }
6048 
6049  return kNotFound;
6050 }
6051 
6052 
6054  uint32_t hash = name->Hash();
6055  for (int number = 0; number < len; number++) {
6056  String* entry = GetKey(number);
6057  if (mode == EXPECT_SORTED && entry->Hash() > hash) break;
6058  if (name->Equals(entry) && !IsNullDescriptor(number)) {
6059  return number;
6060  }
6061  }
6062  return kNotFound;
6063 }
6064 
6065 
6067  Heap* heap = GetHeap();
6068  AccessorPair* copy;
6069  { MaybeObject* maybe_copy = heap->AllocateAccessorPair();
6070  if (!maybe_copy->To(&copy)) return maybe_copy;
6071  }
6072  copy->set_getter(getter()->IsMap() ? heap->the_hole_value() : getter());
6073  copy->set_setter(setter()->IsMap() ? heap->the_hole_value() : setter());
6074  return copy;
6075 }
6076 
6077 
6079  Object* accessor = get(component);
6080  return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
6081 }
6082 
6083 
6084 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count,
6085  PretenureFlag pretenure) {
6086  ASSERT(deopt_entry_count > 0);
6087  return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count),
6088  pretenure);
6089 }
6090 
6091 
6092 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points,
6093  PretenureFlag pretenure) {
6094  if (number_of_deopt_points == 0) return HEAP->empty_fixed_array();
6095  return HEAP->AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points),
6096  pretenure);
6097 }
6098 
6099 
6100 #ifdef DEBUG
6101 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
6102  if (IsEmpty()) return other->IsEmpty();
6103  if (other->IsEmpty()) return false;
6104  if (length() != other->length()) return false;
6105  for (int i = 0; i < length(); ++i) {
6106  if (get(i) != other->get(i)) return false;
6107  }
6108  return true;
6109 }
6110 #endif
6111 
6112 
6114  if (!Isolate::Current()->heap()->Contains(this)) return false;
6115  return true;
6116 }
6117 
6118 
6120  int length = this->length();
6121  StringShape shape(this);
6122  String* string = this;
6123  int offset = 0;
6124  if (shape.representation_tag() == kConsStringTag) {
6125  ConsString* cons = ConsString::cast(string);
6126  if (cons->second()->length() != 0) {
6127  return FlatContent();
6128  }
6129  string = cons->first();
6130  shape = StringShape(string);
6131  }
6132  if (shape.representation_tag() == kSlicedStringTag) {
6133  SlicedString* slice = SlicedString::cast(string);
6134  offset = slice->offset();
6135  string = slice->parent();
6136  shape = StringShape(string);
6137  ASSERT(shape.representation_tag() != kConsStringTag &&
6138  shape.representation_tag() != kSlicedStringTag);
6139  }
6140  if (shape.encoding_tag() == kAsciiStringTag) {
6141  const char* start;
6142  if (shape.representation_tag() == kSeqStringTag) {
6143  start = SeqAsciiString::cast(string)->GetChars();
6144  } else {
6145  start = ExternalAsciiString::cast(string)->GetChars();
6146  }
6147  return FlatContent(Vector<const char>(start + offset, length));
6148  } else {
6149  ASSERT(shape.encoding_tag() == kTwoByteStringTag);
6150  const uc16* start;
6151  if (shape.representation_tag() == kSeqStringTag) {
6152  start = SeqTwoByteString::cast(string)->GetChars();
6153  } else {
6154  start = ExternalTwoByteString::cast(string)->GetChars();
6155  }
6156  return FlatContent(Vector<const uc16>(start + offset, length));
6157  }
6158 }
6159 
6160 
6162  RobustnessFlag robust_flag,
6163  int offset,
6164  int length,
6165  int* length_return) {
6166  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
6167  return SmartArrayPointer<char>(NULL);
6168  }
6169  Heap* heap = GetHeap();
6170 
6171  // Negative length means the to the end of the string.
6172  if (length < 0) length = kMaxInt - offset;
6173 
6174  // Compute the size of the UTF-8 string. Start at the specified offset.
6177  buffer->Reset(offset, this);
6178  int character_position = offset;
6179  int utf8_bytes = 0;
6181  while (buffer->has_more() && character_position++ < offset + length) {
6182  uint16_t character = buffer->GetNext();
6183  utf8_bytes += unibrow::Utf8::Length(character, last);
6184  last = character;
6185  }
6186 
6187  if (length_return) {
6188  *length_return = utf8_bytes;
6189  }
6190 
6191  char* result = NewArray<char>(utf8_bytes + 1);
6192 
6193  // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
6194  buffer->Rewind();
6195  buffer->Seek(offset);
6196  character_position = offset;
6197  int utf8_byte_position = 0;
6199  while (buffer->has_more() && character_position++ < offset + length) {
6200  uint16_t character = buffer->GetNext();
6201  if (allow_nulls == DISALLOW_NULLS && character == 0) {
6202  character = ' ';
6203  }
6204  utf8_byte_position +=
6205  unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
6206  last = character;
6207  }
6208  result[utf8_byte_position] = 0;
6209  return SmartArrayPointer<char>(result);
6210 }
6211 
6212 
6214  RobustnessFlag robust_flag,
6215  int* length_return) {
6216  return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
6217 }
6218 
6219 
6221  return GetTwoByteData(0);
6222 }
6223 
6224 
6225 const uc16* String::GetTwoByteData(unsigned start) {
6226  ASSERT(!IsAsciiRepresentationUnderneath());
6227  switch (StringShape(this).representation_tag()) {
6228  case kSeqStringTag:
6229  return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
6230  case kExternalStringTag:
6231  return ExternalTwoByteString::cast(this)->
6232  ExternalTwoByteStringGetData(start);
6233  case kSlicedStringTag: {
6234  SlicedString* slice = SlicedString::cast(this);
6235  return slice->parent()->GetTwoByteData(start + slice->offset());
6236  }
6237  case kConsStringTag:
6238  UNREACHABLE();
6239  return NULL;
6240  }
6241  UNREACHABLE();
6242  return NULL;
6243 }
6244 
6245 
6247  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
6248  return SmartArrayPointer<uc16>();
6249  }
6250  Heap* heap = GetHeap();
6251 
6254  buffer->Reset(this);
6255 
6256  uc16* result = NewArray<uc16>(length() + 1);
6257 
6258  int i = 0;
6259  while (buffer->has_more()) {
6260  uint16_t character = buffer->GetNext();
6261  result[i++] = character;
6262  }
6263  result[i] = 0;
6264  return SmartArrayPointer<uc16>(result);
6265 }
6266 
6267 
6269  return reinterpret_cast<uc16*>(
6270  reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
6271 }
6272 
6273 
6275  unsigned* offset_ptr,
6276  unsigned max_chars) {
6277  unsigned chars_read = 0;
6278  unsigned offset = *offset_ptr;
6279  while (chars_read < max_chars) {
6280  uint16_t c = *reinterpret_cast<uint16_t*>(
6281  reinterpret_cast<char*>(this) -
6282  kHeapObjectTag + kHeaderSize + offset * kShortSize);
6283  if (c <= kMaxAsciiCharCode) {
6284  // Fast case for ASCII characters. Cursor is an input output argument.
6286  rbb->util_buffer,
6287  rbb->capacity,
6288  rbb->cursor)) {
6289  break;
6290  }
6291  } else {
6293  rbb->util_buffer,
6294  rbb->capacity,
6295  rbb->cursor)) {
6296  break;
6297  }
6298  }
6299  offset++;
6300  chars_read++;
6301  }
6302  *offset_ptr = offset;
6303  rbb->remaining += chars_read;
6304 }
6305 
6306 
6308  unsigned* remaining,
6309  unsigned* offset_ptr,
6310  unsigned max_chars) {
6311  const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) -
6312  kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize;
6313  *remaining = max_chars;
6314  *offset_ptr += max_chars;
6315  return b;
6316 }
6317 
6318 
6319 // This will iterate unless the block of string data spans two 'halves' of
6320 // a ConsString, in which case it will recurse. Since the block of string
6321 // data to be read has a maximum size this limits the maximum recursion
6322 // depth to something sane. Since C++ does not have tail call recursion
6323 // elimination, the iteration must be explicit. Since this is not an
6324 // -IntoBuffer method it can delegate to one of the efficient
6325 // *AsciiStringReadBlock routines.
6327  unsigned* offset_ptr,
6328  unsigned max_chars) {
6329  ConsString* current = this;
6330  unsigned offset = *offset_ptr;
6331  int offset_correction = 0;
6332 
6333  while (true) {
6334  String* left = current->first();
6335  unsigned left_length = (unsigned)left->length();
6336  if (left_length > offset &&
6337  (max_chars <= left_length - offset ||
6338  (rbb->capacity <= left_length - offset &&
6339  (max_chars = left_length - offset, true)))) { // comma operator!
6340  // Left hand side only - iterate unless we have reached the bottom of
6341  // the cons tree. The assignment on the left of the comma operator is
6342  // in order to make use of the fact that the -IntoBuffer routines can
6343  // produce at most 'capacity' characters. This enables us to postpone
6344  // the point where we switch to the -IntoBuffer routines (below) in order
6345  // to maximize the chances of delegating a big chunk of work to the
6346  // efficient *AsciiStringReadBlock routines.
6347  if (StringShape(left).IsCons()) {
6348  current = ConsString::cast(left);
6349  continue;
6350  } else {
6351  const unibrow::byte* answer =
6352  String::ReadBlock(left, rbb, &offset, max_chars);
6353  *offset_ptr = offset + offset_correction;
6354  return answer;
6355  }
6356  } else if (left_length <= offset) {
6357  // Right hand side only - iterate unless we have reached the bottom of
6358  // the cons tree.
6359  String* right = current->second();
6360  offset -= left_length;
6361  offset_correction += left_length;
6362  if (StringShape(right).IsCons()) {
6363  current = ConsString::cast(right);
6364  continue;
6365  } else {
6366  const unibrow::byte* answer =
6367  String::ReadBlock(right, rbb, &offset, max_chars);
6368  *offset_ptr = offset + offset_correction;
6369  return answer;
6370  }
6371  } else {
6372  // The block to be read spans two sides of the ConsString, so we call the
6373  // -IntoBuffer version, which will recurse. The -IntoBuffer methods
6374  // are able to assemble data from several part strings because they use
6375  // the util_buffer to store their data and never return direct pointers
6376  // to their storage. We don't try to read more than the buffer capacity
6377  // here or we can get too much recursion.
6378  ASSERT(rbb->remaining == 0);
6379  ASSERT(rbb->cursor == 0);
6381  rbb,
6382  &offset,
6383  max_chars > rbb->capacity ? rbb->capacity : max_chars);
6384  *offset_ptr = offset + offset_correction;
6385  return rbb->util_buffer;
6386  }
6387  }
6388 }
6389 
6390 
6392  unsigned* remaining,
6393  unsigned* offset_ptr,
6394  unsigned max_chars) {
6395  // Cast const char* to unibrow::byte* (signedness difference).
6396  const unibrow::byte* b =
6397  reinterpret_cast<const unibrow::byte*>(GetChars()) + *offset_ptr;
6398  *remaining = max_chars;
6399  *offset_ptr += max_chars;
6400  return b;
6401 }
6402 
6403 
6405  ReadBlockBuffer* rbb,
6406  unsigned* offset_ptr,
6407  unsigned max_chars) {
6408  unsigned chars_read = 0;
6409  unsigned offset = *offset_ptr;
6410  const uint16_t* data = GetChars();
6411  while (chars_read < max_chars) {
6412  uint16_t c = data[offset];
6413  if (c <= kMaxAsciiCharCode) {
6414  // Fast case for ASCII characters. Cursor is an input output argument.
6416  rbb->util_buffer,
6417  rbb->capacity,
6418  rbb->cursor))
6419  break;
6420  } else {
6422  rbb->util_buffer,
6423  rbb->capacity,
6424  rbb->cursor))
6425  break;
6426  }
6427  offset++;
6428  chars_read++;
6429  }
6430  *offset_ptr = offset;
6431  rbb->remaining += chars_read;
6432 }
6433 
6434 
6436  unsigned* offset_ptr,
6437  unsigned max_chars) {
6438  unsigned capacity = rbb->capacity - rbb->cursor;
6439  if (max_chars > capacity) max_chars = capacity;
6440  memcpy(rbb->util_buffer + rbb->cursor,
6441  reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize +
6442  *offset_ptr * kCharSize,
6443  max_chars);
6444  rbb->remaining += max_chars;
6445  *offset_ptr += max_chars;
6446  rbb->cursor += max_chars;
6447 }
6448 
6449 
6451  ReadBlockBuffer* rbb,
6452  unsigned* offset_ptr,
6453  unsigned max_chars) {
6454  unsigned capacity = rbb->capacity - rbb->cursor;
6455  if (max_chars > capacity) max_chars = capacity;
6456  memcpy(rbb->util_buffer + rbb->cursor, GetChars() + *offset_ptr, max_chars);
6457  rbb->remaining += max_chars;
6458  *offset_ptr += max_chars;
6459  rbb->cursor += max_chars;
6460 }
6461 
6462 
6463 // This method determines the type of string involved and then copies
6464 // a whole chunk of characters into a buffer, or returns a pointer to a buffer
6465 // where they can be found. The pointer is not necessarily valid across a GC
6466 // (see AsciiStringReadBlock).
6468  ReadBlockBuffer* rbb,
6469  unsigned* offset_ptr,
6470  unsigned max_chars) {
6471  ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
6472  if (max_chars == 0) {
6473  rbb->remaining = 0;
6474  return NULL;
6475  }
6476  switch (StringShape(input).representation_tag()) {
6477  case kSeqStringTag:
6478  if (input->IsAsciiRepresentation()) {
6479  SeqAsciiString* str = SeqAsciiString::cast(input);
6480  return str->SeqAsciiStringReadBlock(&rbb->remaining,
6481  offset_ptr,
6482  max_chars);
6483  } else {
6486  offset_ptr,
6487  max_chars);
6488  return rbb->util_buffer;
6489  }
6490  case kConsStringTag:
6491  return ConsString::cast(input)->ConsStringReadBlock(rbb,
6492  offset_ptr,
6493  max_chars);
6494  case kExternalStringTag:
6495  if (input->IsAsciiRepresentation()) {
6497  &rbb->remaining,
6498  offset_ptr,
6499  max_chars);
6500  } else {
6502  ExternalTwoByteStringReadBlockIntoBuffer(rbb,
6503  offset_ptr,
6504  max_chars);
6505  return rbb->util_buffer;
6506  }
6507  case kSlicedStringTag:
6508  return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
6509  offset_ptr,
6510  max_chars);
6511  default:
6512  break;
6513  }
6514 
6515  UNREACHABLE();
6516  return 0;
6517 }
6518 
6519 
6520 void Relocatable::PostGarbageCollectionProcessing() {
6521  Isolate* isolate = Isolate::Current();
6522  Relocatable* current = isolate->relocatable_top();
6523  while (current != NULL) {
6524  current->PostGarbageCollection();
6525  current = current->prev_;
6526  }
6527 }
6528 
6529 
6530 // Reserve space for statics needing saving and restoring.
6531 int Relocatable::ArchiveSpacePerThread() {
6532  return sizeof(Isolate::Current()->relocatable_top());
6533 }
6534 
6535 
6536 // Archive statics that are thread local.
6537 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
6538  *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
6539  isolate->set_relocatable_top(NULL);
6540  return to + ArchiveSpacePerThread();
6541 }
6542 
6543 
6544 // Restore statics that are thread local.
6545 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
6546  isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
6547  return from + ArchiveSpacePerThread();
6548 }
6549 
6550 
6551 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
6552  Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
6553  Iterate(v, top);
6554  return thread_storage + ArchiveSpacePerThread();
6555 }
6556 
6557 
6558 void Relocatable::Iterate(ObjectVisitor* v) {
6559  Isolate* isolate = Isolate::Current();
6560  Iterate(v, isolate->relocatable_top());
6561 }
6562 
6563 
6564 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
6565  Relocatable* current = top;
6566  while (current != NULL) {
6567  current->IterateInstance(v);
6568  current = current->prev_;
6569  }
6570 }
6571 
6572 
6574  : Relocatable(isolate),
6575  str_(str.location()),
6576  length_(str->length()) {
6578 }
6579 
6580 
6582  : Relocatable(isolate),
6583  str_(0),
6584  is_ascii_(true),
6585  length_(input.length()),
6586  start_(input.start()) { }
6587 
6588 
6590  if (str_ == NULL) return;
6591  Handle<String> str(str_);
6592  ASSERT(str->IsFlat());
6593  String::FlatContent content = str->GetFlatContent();
6594  ASSERT(content.IsFlat());
6595  is_ascii_ = content.IsAscii();
6596  if (is_ascii_) {
6597  start_ = content.ToAsciiVector().start();
6598  } else {
6599  start_ = content.ToUC16Vector().start();
6600  }
6601 }
6602 
6603 
6604 void StringInputBuffer::Seek(unsigned pos) {
6605  Reset(pos, input_);
6606 }
6607 
6608 
6609 void SafeStringInputBuffer::Seek(unsigned pos) {
6610  Reset(pos, input_);
6611 }
6612 
6613 
6614 // This method determines the type of string involved and then copies
6615 // a whole chunk of characters into a buffer. It can be used with strings
6616 // that have been glued together to form a ConsString and which must cooperate
6617 // to fill up a buffer.
6619  ReadBlockBuffer* rbb,
6620  unsigned* offset_ptr,
6621  unsigned max_chars) {
6622  ASSERT(*offset_ptr <= (unsigned)input->length());
6623  if (max_chars == 0) return;
6624 
6625  switch (StringShape(input).representation_tag()) {
6626  case kSeqStringTag:
6627  if (input->IsAsciiRepresentation()) {
6629  offset_ptr,
6630  max_chars);
6631  return;
6632  } else {
6634  offset_ptr,
6635  max_chars);
6636  return;
6637  }
6638  case kConsStringTag:
6640  offset_ptr,
6641  max_chars);
6642  return;
6643  case kExternalStringTag:
6644  if (input->IsAsciiRepresentation()) {
6645  ExternalAsciiString::cast(input)->
6646  ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
6647  } else {
6649  ExternalTwoByteStringReadBlockIntoBuffer(rbb,
6650  offset_ptr,
6651  max_chars);
6652  }
6653  return;
6654  case kSlicedStringTag:
6656  offset_ptr,
6657  max_chars);
6658  return;
6659  default:
6660  break;
6661  }
6662 
6663  UNREACHABLE();
6664  return;
6665 }
6666 
6667 
6669  unibrow::byte* util_buffer,
6670  unsigned capacity,
6671  unsigned* remaining,
6672  unsigned* offset_ptr) {
6673  ASSERT(*offset_ptr <= (unsigned)input->length());
6674  unsigned chars = input->length() - *offset_ptr;
6675  ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
6676  const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
6677  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
6678  *remaining = rbb.remaining;
6679  return answer;
6680 }
6681 
6682 
6684  unibrow::byte* util_buffer,
6685  unsigned capacity,
6686  unsigned* remaining,
6687  unsigned* offset_ptr) {
6688  Handle<String> input(raw_input);
6689  ASSERT(*offset_ptr <= (unsigned)input->length());
6690  unsigned chars = input->length() - *offset_ptr;
6691  if (chars > capacity) chars = capacity;
6692  ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
6693  ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
6694  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
6695  *remaining = rbb.remaining;
6696  return rbb.util_buffer;
6697 }
6698 
6699 
6700 // This will iterate unless the block of string data spans two 'halves' of
6701 // a ConsString, in which case it will recurse. Since the block of string
6702 // data to be read has a maximum size this limits the maximum recursion
6703 // depth to something sane. Since C++ does not have tail call recursion
6704 // elimination, the iteration must be explicit.
6706  unsigned* offset_ptr,
6707  unsigned max_chars) {
6708  ConsString* current = this;
6709  unsigned offset = *offset_ptr;
6710  int offset_correction = 0;
6711 
6712  while (true) {
6713  String* left = current->first();
6714  unsigned left_length = (unsigned)left->length();
6715  if (left_length > offset &&
6716  max_chars <= left_length - offset) {
6717  // Left hand side only - iterate unless we have reached the bottom of
6718  // the cons tree.
6719  if (StringShape(left).IsCons()) {
6720  current = ConsString::cast(left);
6721  continue;
6722  } else {
6723  String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
6724  *offset_ptr = offset + offset_correction;
6725  return;
6726  }
6727  } else if (left_length <= offset) {
6728  // Right hand side only - iterate unless we have reached the bottom of
6729  // the cons tree.
6730  offset -= left_length;
6731  offset_correction += left_length;
6732  String* right = current->second();
6733  if (StringShape(right).IsCons()) {
6734  current = ConsString::cast(right);
6735  continue;
6736  } else {
6737  String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
6738  *offset_ptr = offset + offset_correction;
6739  return;
6740  }
6741  } else {
6742  // The block to be read spans two sides of the ConsString, so we recurse.
6743  // First recurse on the left.
6744  max_chars -= left_length - offset;
6745  String::ReadBlockIntoBuffer(left, rbb, &offset, left_length - offset);
6746  // We may have reached the max or there may not have been enough space
6747  // in the buffer for the characters in the left hand side.
6748  if (offset == left_length) {
6749  // Recurse on the right.
6750  String* right = String::cast(current->second());
6751  offset -= left_length;
6752  offset_correction += left_length;
6753  String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
6754  }
6755  *offset_ptr = offset + offset_correction;
6756  return;
6757  }
6758  }
6759 }
6760 
6761 
6763  ASSERT(index >= 0 && index < this->length());
6764 
6765  // Check for a flattened cons string
6766  if (second()->length() == 0) {
6767  String* left = first();
6768  return left->Get(index);
6769  }
6770 
6771  String* string = String::cast(this);
6772 
6773  while (true) {
6774  if (StringShape(string).IsCons()) {
6775  ConsString* cons_string = ConsString::cast(string);
6776  String* left = cons_string->first();
6777  if (left->length() > index) {
6778  string = left;
6779  } else {
6780  index -= left->length();
6781  string = cons_string->second();
6782  }
6783  } else {
6784  return string->Get(index);
6785  }
6786  }
6787 
6788  UNREACHABLE();
6789  return 0;
6790 }
6791 
6792 
6794  return parent()->Get(offset() + index);
6795 }
6796 
6797 
6799  ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6800  unsigned offset = this->offset();
6801  *offset_ptr += offset;
6803  buffer, offset_ptr, chars);
6804  *offset_ptr -= offset;
6805  return answer;
6806 }
6807 
6808 
6810  ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6811  unsigned offset = this->offset();
6812  *offset_ptr += offset;
6814  buffer, offset_ptr, chars);
6815  *offset_ptr -= offset;
6816 }
6817 
6818 template <typename sinkchar>
6820  sinkchar* sink,
6821  int f,
6822  int t) {
6823  String* source = src;
6824  int from = f;
6825  int to = t;
6826  while (true) {
6827  ASSERT(0 <= from && from <= to && to <= source->length());
6828  switch (StringShape(source).full_representation_tag()) {
6830  CopyChars(sink,
6831  ExternalAsciiString::cast(source)->GetChars() + from,
6832  to - from);
6833  return;
6834  }
6836  const uc16* data =
6838  CopyChars(sink,
6839  data + from,
6840  to - from);
6841  return;
6842  }
6843  case kAsciiStringTag | kSeqStringTag: {
6844  CopyChars(sink,
6845  SeqAsciiString::cast(source)->GetChars() + from,
6846  to - from);
6847  return;
6848  }
6850  CopyChars(sink,
6851  SeqTwoByteString::cast(source)->GetChars() + from,
6852  to - from);
6853  return;
6854  }
6857  ConsString* cons_string = ConsString::cast(source);
6858  String* first = cons_string->first();
6859  int boundary = first->length();
6860  if (to - boundary >= boundary - from) {
6861  // Right hand side is longer. Recurse over left.
6862  if (from < boundary) {
6863  WriteToFlat(first, sink, from, boundary);
6864  sink += boundary - from;
6865  from = 0;
6866  } else {
6867  from -= boundary;
6868  }
6869  to -= boundary;
6870  source = cons_string->second();
6871  } else {
6872  // Left hand side is longer. Recurse over right.
6873  if (to > boundary) {
6874  String* second = cons_string->second();
6875  // When repeatedly appending to a string, we get a cons string that
6876  // is unbalanced to the left, a list, essentially. We inline the
6877  // common case of sequential ascii right child.
6878  if (to - boundary == 1) {
6879  sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
6880  } else if (second->IsSeqAsciiString()) {
6881  CopyChars(sink + boundary - from,
6882  SeqAsciiString::cast(second)->GetChars(),
6883  to - boundary);
6884  } else {
6885  WriteToFlat(second,
6886  sink + boundary - from,
6887  0,
6888  to - boundary);
6889  }
6890  to = boundary;
6891  }
6892  source = first;
6893  }
6894  break;
6895  }
6898  SlicedString* slice = SlicedString::cast(source);
6899  unsigned offset = slice->offset();
6900  WriteToFlat(slice->parent(), sink, from + offset, to + offset);
6901  return;
6902  }
6903  }
6904  }
6905 }
6906 
6907 
6908 template <typename IteratorA, typename IteratorB>
6909 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
6910  // General slow case check. We know that the ia and ib iterators
6911  // have the same length.
6912  while (ia->has_more()) {
6913  uint32_t ca = ia->GetNext();
6914  uint32_t cb = ib->GetNext();
6917  if (ca != cb)
6918  return false;
6919  }
6920  return true;
6921 }
6922 
6923 
6924 // Compares the contents of two strings by reading and comparing
6925 // int-sized blocks of characters.
6926 template <typename Char>
6927 static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
6928  int length = a.length();
6929  ASSERT_EQ(length, b.length());
6930  const Char* pa = a.start();
6931  const Char* pb = b.start();
6932  int i = 0;
6933 #ifndef V8_HOST_CAN_READ_UNALIGNED
6934  // If this architecture isn't comfortable reading unaligned ints
6935  // then we have to check that the strings are aligned before
6936  // comparing them blockwise.
6937  const int kAlignmentMask = sizeof(uint32_t) - 1; // NOLINT
6938  uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
6939  uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
6940  if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
6941 #endif
6942  const int kStepSize = sizeof(int) / sizeof(Char); // NOLINT
6943  int endpoint = length - kStepSize;
6944  // Compare blocks until we reach near the end of the string.
6945  for (; i <= endpoint; i += kStepSize) {
6946  uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i);
6947  uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i);
6948  if (wa != wb) {
6949  return false;
6950  }
6951  }
6952 #ifndef V8_HOST_CAN_READ_UNALIGNED
6953  }
6954 #endif
6955  // Compare the remaining characters that didn't fit into a block.
6956  for (; i < length; i++) {
6957  if (a[i] != b[i]) {
6958  return false;
6959  }
6960  }
6961  return true;
6962 }
6963 
6964 
6965 template <typename IteratorA>
6966 static inline bool CompareStringContentsPartial(Isolate* isolate,
6967  IteratorA* ia,
6968  String* b) {
6969  String::FlatContent content = b->GetFlatContent();
6970  if (content.IsFlat()) {
6971  if (content.IsAscii()) {
6972  VectorIterator<char> ib(content.ToAsciiVector());
6973  return CompareStringContents(ia, &ib);
6974  } else {
6975  VectorIterator<uc16> ib(content.ToUC16Vector());
6976  return CompareStringContents(ia, &ib);
6977  }
6978  } else {
6979  isolate->objects_string_compare_buffer_b()->Reset(0, b);
6980  return CompareStringContents(ia,
6981  isolate->objects_string_compare_buffer_b());
6982  }
6983 }
6984 
6985 
6986 bool String::SlowEquals(String* other) {
6987  // Fast check: negative check with lengths.
6988  int len = length();
6989  if (len != other->length()) return false;
6990  if (len == 0) return true;
6991 
6992  // Fast check: if hash code is computed for both strings
6993  // a fast negative check can be performed.
6994  if (HasHashCode() && other->HasHashCode()) {
6995 #ifdef DEBUG
6997  if (Hash() != other->Hash()) {
6998  bool found_difference = false;
6999  for (int i = 0; i < len; i++) {
7000  if (Get(i) != other->Get(i)) {
7001  found_difference = true;
7002  break;
7003  }
7004  }
7005  ASSERT(found_difference);
7006  }
7007  }
7008 #endif
7009  if (Hash() != other->Hash()) return false;
7010  }
7011 
7012  // We know the strings are both non-empty. Compare the first chars
7013  // before we try to flatten the strings.
7014  if (this->Get(0) != other->Get(0)) return false;
7015 
7016  String* lhs = this->TryFlattenGetString();
7017  String* rhs = other->TryFlattenGetString();
7018 
7019  if (StringShape(lhs).IsSequentialAscii() &&
7020  StringShape(rhs).IsSequentialAscii()) {
7021  const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
7022  const char* str2 = SeqAsciiString::cast(rhs)->GetChars();
7023  return CompareRawStringContents(Vector<const char>(str1, len),
7024  Vector<const char>(str2, len));
7025  }
7026 
7027  Isolate* isolate = GetIsolate();
7028  String::FlatContent lhs_content = lhs->GetFlatContent();
7029  String::FlatContent rhs_content = rhs->GetFlatContent();
7030  if (lhs_content.IsFlat()) {
7031  if (lhs_content.IsAscii()) {
7032  Vector<const char> vec1 = lhs_content.ToAsciiVector();
7033  if (rhs_content.IsFlat()) {
7034  if (rhs_content.IsAscii()) {
7035  Vector<const char> vec2 = rhs_content.ToAsciiVector();
7036  return CompareRawStringContents(vec1, vec2);
7037  } else {
7038  VectorIterator<char> buf1(vec1);
7039  VectorIterator<uc16> ib(rhs_content.ToUC16Vector());
7040  return CompareStringContents(&buf1, &ib);
7041  }
7042  } else {
7043  VectorIterator<char> buf1(vec1);
7044  isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
7045  return CompareStringContents(&buf1,
7046  isolate->objects_string_compare_buffer_b());
7047  }
7048  } else {
7049  Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
7050  if (rhs_content.IsFlat()) {
7051  if (rhs_content.IsAscii()) {
7052  VectorIterator<uc16> buf1(vec1);
7053  VectorIterator<char> ib(rhs_content.ToAsciiVector());
7054  return CompareStringContents(&buf1, &ib);
7055  } else {
7056  Vector<const uc16> vec2(rhs_content.ToUC16Vector());
7057  return CompareRawStringContents(vec1, vec2);
7058  }
7059  } else {
7060  VectorIterator<uc16> buf1(vec1);
7061  isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
7062  return CompareStringContents(&buf1,
7063  isolate->objects_string_compare_buffer_b());
7064  }
7065  }
7066  } else {
7067  isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
7068  return CompareStringContentsPartial(isolate,
7069  isolate->objects_string_compare_buffer_a(), rhs);
7070  }
7071 }
7072 
7073 
7075  if (StringShape(this).IsSymbol()) return false;
7076 
7077  Map* map = this->map();
7078  Heap* heap = GetHeap();
7079  if (map == heap->string_map()) {
7080  this->set_map(heap->undetectable_string_map());
7081  return true;
7082  } else if (map == heap->ascii_string_map()) {
7083  this->set_map(heap->undetectable_ascii_string_map());
7084  return true;
7085  }
7086  // Rest cannot be marked as undetectable
7087  return false;
7088 }
7089 
7090 
7092  Isolate* isolate = GetIsolate();
7093  int slen = length();
7095  decoder(isolate->unicode_cache()->utf8_decoder());
7096  decoder->Reset(str.start(), str.length());
7097  int i;
7098  for (i = 0; i < slen && decoder->has_more(); i++) {
7099  uint32_t r = decoder->GetNext();
7101  if (i > slen - 1) return false;
7102  if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
7103  if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
7104  } else {
7105  if (Get(i) != r) return false;
7106  }
7107  }
7108  return i == slen && !decoder->has_more();
7109 }
7110 
7111 
7113  int slen = length();
7114  if (str.length() != slen) return false;
7115  FlatContent content = GetFlatContent();
7116  if (content.IsAscii()) {
7117  return CompareChars(content.ToAsciiVector().start(),
7118  str.start(), slen) == 0;
7119  }
7120  for (int i = 0; i < slen; i++) {
7121  if (Get(i) != static_cast<uint16_t>(str[i])) return false;
7122  }
7123  return true;
7124 }
7125 
7126 
7128  int slen = length();
7129  if (str.length() != slen) return false;
7130  FlatContent content = GetFlatContent();
7131  if (content.IsTwoByte()) {
7132  return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
7133  }
7134  for (int i = 0; i < slen; i++) {
7135  if (Get(i) != str[i]) return false;
7136  }
7137  return true;
7138 }
7139 
7140 
7141 uint32_t String::ComputeAndSetHash() {
7142  // Should only be called if hash code has not yet been computed.
7143  ASSERT(!HasHashCode());
7144 
7145  const int len = length();
7146 
7147  // Compute the hash code.
7148  uint32_t field = 0;
7149  if (StringShape(this).IsSequentialAscii()) {
7150  field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(),
7151  len,
7152  GetHeap()->HashSeed());
7153  } else if (StringShape(this).IsSequentialTwoByte()) {
7154  field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(),
7155  len,
7156  GetHeap()->HashSeed());
7157  } else {
7158  StringInputBuffer buffer(this);
7159  field = ComputeHashField(&buffer, len, GetHeap()->HashSeed());
7160  }
7161 
7162  // Store the hash code in the object.
7163  set_hash_field(field);
7164 
7165  // Check the hash code is there.
7166  ASSERT(HasHashCode());
7167  uint32_t result = field >> kHashShift;
7168  ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
7169  return result;
7170 }
7171 
7172 
7174  uint32_t* index,
7175  int length) {
7176  if (length == 0 || length > kMaxArrayIndexSize) return false;
7177  uc32 ch = buffer->GetNext();
7178 
7179  // If the string begins with a '0' character, it must only consist
7180  // of it to be a legal array index.
7181  if (ch == '0') {
7182  *index = 0;
7183  return length == 1;
7184  }
7185 
7186  // Convert string to uint32 array index; character by character.
7187  int d = ch - '0';
7188  if (d < 0 || d > 9) return false;
7189  uint32_t result = d;
7190  while (buffer->has_more()) {
7191  d = buffer->GetNext() - '0';
7192  if (d < 0 || d > 9) return false;
7193  // Check that the new result is below the 32 bit limit.
7194  if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
7195  result = (result * 10) + d;
7196  }
7197 
7198  *index = result;
7199  return true;
7200 }
7201 
7202 
7203 bool String::SlowAsArrayIndex(uint32_t* index) {
7205  Hash(); // force computation of hash code
7206  uint32_t field = hash_field();
7207  if ((field & kIsNotArrayIndexMask) != 0) return false;
7208  // Isolate the array index form the full hash field.
7209  *index = (kArrayIndexHashMask & field) >> kHashShift;
7210  return true;
7211  } else {
7212  StringInputBuffer buffer(this);
7213  return ComputeArrayIndex(&buffer, index, length());
7214  }
7215 }
7216 
7217 
7218 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
7219  // For array indexes mix the length into the hash as an array index could
7220  // be zero.
7221  ASSERT(length > 0);
7225 
7226  value <<= String::kHashShift;
7227  value |= length << String::kArrayIndexHashLengthShift;
7228 
7229  ASSERT((value & String::kIsNotArrayIndexMask) == 0);
7231  (value & String::kContainsCachedArrayIndexMask) == 0);
7232  return value;
7233 }
7234 
7235 
7238  AddCharacter(lead);
7240  AddCharacter(trail);
7241 }
7242 
7243 
7246  AddCharacterNoIndex(lead);
7248  AddCharacterNoIndex(trail);
7249 }
7250 
7251 
7253  ASSERT(is_valid());
7254  if (length_ <= String::kMaxHashCalcLength) {
7255  if (is_array_index()) {
7256  return MakeArrayIndexHash(array_index(), length_);
7257  }
7258  return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask;
7259  } else {
7260  return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
7261  }
7262 }
7263 
7264 
7266  int length,
7267  uint32_t seed) {
7268  StringHasher hasher(length, seed);
7269 
7270  // Very long strings have a trivial hash that doesn't inspect the
7271  // string contents.
7272  if (hasher.has_trivial_hash()) {
7273  return hasher.GetHashField();
7274  }
7275 
7276  // Do the iterative array index computation as long as there is a
7277  // chance this is an array index.
7278  while (buffer->has_more() && hasher.is_array_index()) {
7279  hasher.AddCharacter(buffer->GetNext());
7280  }
7281 
7282  // Process the remaining characters without updating the array
7283  // index.
7284  while (buffer->has_more()) {
7285  hasher.AddCharacterNoIndex(buffer->GetNext());
7286  }
7287 
7288  return hasher.GetHashField();
7289 }
7290 
7291 
7292 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) {
7293  Heap* heap = GetHeap();
7294  if (start == 0 && end == length()) return this;
7295  MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure);
7296  return result;
7297 }
7298 
7299 
7300 void String::PrintOn(FILE* file) {
7301  int length = this->length();
7302  for (int i = 0; i < length; i++) {
7303  fprintf(file, "%c", Get(i));
7304  }
7305 }
7306 
7307 
7308 // Clear a possible back pointer in case the transition leads to a dead map.
7309 // Return true in case a back pointer has been cleared and false otherwise.
7310 static bool ClearBackPointer(Heap* heap, Object* target) {
7311  ASSERT(target->IsMap());
7312  Map* map = Map::cast(target);
7313  if (Marking::MarkBitFrom(map).Get()) return false;
7314  map->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
7315  return true;
7316 }
7317 
7318 
7322  if (d->IsEmpty()) return;
7323  Smi* NullDescriptorDetails =
7324  PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
7325  for (int i = 0; i < d->number_of_descriptors(); ++i) {
7326  // If the pair (value, details) is a map transition, check if the target is
7327  // live. If not, null the descriptor. Also drop the back pointer for that
7328  // map transition, so that this map is not reached again by following a back
7329  // pointer from that non-live map.
7330  bool keep_entry = false;
7331  PropertyDetails details(d->GetDetails(i));
7332  switch (details.type()) {
7333  case MAP_TRANSITION:
7334  case CONSTANT_TRANSITION:
7335  keep_entry = !ClearBackPointer(heap, d->GetValue(i));
7336  break;
7337  case CALLBACKS: {
7338  Object* object = d->GetValue(i);
7339  if (object->IsAccessorPair()) {
7340  AccessorPair* accessors = AccessorPair::cast(object);
7341  Object* getter = accessors->getter();
7342  if (getter->IsMap()) {
7343  if (ClearBackPointer(heap, getter)) {
7344  accessors->set_getter(heap->the_hole_value());
7345  } else {
7346  keep_entry = true;
7347  }
7348  } else if (!getter->IsTheHole()) {
7349  keep_entry = true;
7350  }
7351  Object* setter = accessors->setter();
7352  if (setter->IsMap()) {
7353  if (ClearBackPointer(heap, setter)) {
7354  accessors->set_setter(heap->the_hole_value());
7355  } else {
7356  keep_entry = true;
7357  }
7358  } else if (!getter->IsTheHole()) {
7359  keep_entry = true;
7360  }
7361  } else {
7362  keep_entry = true;
7363  }
7364  break;
7365  }
7366  case NORMAL:
7367  case FIELD:
7368  case CONSTANT_FUNCTION:
7369  case HANDLER:
7370  case INTERCEPTOR:
7371  case NULL_DESCRIPTOR:
7372  keep_entry = true;
7373  break;
7374  }
7375  // Make sure that an entry containing only dead transitions gets collected.
7376  // What we *really* want to do here is removing this entry completely, but
7377  // for technical reasons we can't do this, so we zero it out instead.
7378  if (!keep_entry) {
7379  d->SetDetailsUnchecked(i, NullDescriptorDetails);
7380  d->SetNullValueUnchecked(i, heap);
7381  }
7382  }
7383 }
7384 
7385 
7386 int Map::Hash() {
7387  // For performance reasons we only hash the 3 most variable fields of a map:
7388  // constructor, prototype and bit_field2.
7389 
7390  // Shift away the tag.
7391  int hash = (static_cast<uint32_t>(
7392  reinterpret_cast<uintptr_t>(constructor())) >> 2);
7393 
7394  // XOR-ing the prototype and constructor directly yields too many zero bits
7395  // when the two pointers are close (which is fairly common).
7396  // To avoid this we shift the prototype 4 bits relatively to the constructor.
7397  hash ^= (static_cast<uint32_t>(
7398  reinterpret_cast<uintptr_t>(prototype())) << 2);
7399 
7400  return hash ^ (hash >> 16) ^ bit_field2();
7401 }
7402 
7403 
7406  return
7407  constructor() == other->constructor() &&
7408  prototype() == other->prototype() &&
7410  0 :
7411  other->inobject_properties()) &&
7412  instance_type() == other->instance_type() &&
7413  bit_field() == other->bit_field() &&
7414  bit_field2() == other->bit_field2() &&
7415  (bit_field3() & ~(1<<Map::kIsShared)) ==
7416  (other->bit_field3() & ~(1<<Map::kIsShared));
7417 }
7418 
7419 
7420 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
7421  // Iterate over all fields in the body but take care in dealing with
7422  // the code entry.
7424  v->VisitCodeEntry(this->address() + kCodeEntryOffset);
7425  IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
7426 }
7427 
7428 
7430  ASSERT(is_compiled() && !IsOptimized());
7431  ASSERT(shared()->allows_lazy_compilation() ||
7432  code()->optimizable());
7433  Builtins* builtins = GetIsolate()->builtins();
7434  ReplaceCode(builtins->builtin(Builtins::kLazyRecompile));
7435 }
7436 
7437 
7440  return shared->is_compiled() || CompileLazy(shared, flag);
7441 }
7442 
7443 
7444 static bool CompileLazyHelper(CompilationInfo* info,
7446  // Compile the source information to a code object.
7447  ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
7448  ASSERT(!info->isolate()->has_pending_exception());
7449  bool result = Compiler::CompileLazy(info);
7450  ASSERT(result != Isolate::Current()->has_pending_exception());
7451  if (!result && flag == CLEAR_EXCEPTION) {
7452  info->isolate()->clear_pending_exception();
7453  }
7454  return result;
7455 }
7456 
7457 
7459  ClearExceptionFlag flag) {
7460  CompilationInfo info(shared);
7461  return CompileLazyHelper(&info, flag);
7462 }
7463 
7464 
7466  ClearExceptionFlag flag) {
7467  bool result = true;
7468  if (function->shared()->is_compiled()) {
7469  function->ReplaceCode(function->shared()->code());
7470  function->shared()->set_code_age(0);
7471  } else {
7472  CompilationInfo info(function);
7473  result = CompileLazyHelper(&info, flag);
7474  ASSERT(!result || function->is_compiled());
7475  }
7476  return result;
7477 }
7478 
7479 
7481  int osr_ast_id,
7482  ClearExceptionFlag flag) {
7483  CompilationInfo info(function);
7484  info.SetOptimizing(osr_ast_id);
7485  return CompileLazyHelper(&info, flag);
7486 }
7487 
7488 
7490  if (IsBuiltin()) return false;
7491  SharedFunctionInfo* shared_info = shared();
7492  // Check that the function has a script associated with it.
7493  if (!shared_info->script()->IsScript()) return false;
7494  if (shared_info->optimization_disabled()) return false;
7495  Code* code = shared_info->code();
7496  if (code->kind() == Code::OPTIMIZED_FUNCTION) return true;
7497  // If we never ran this (unlikely) then lets try to optimize it.
7498  if (code->kind() != Code::FUNCTION) return true;
7499  return code->optimizable();
7500 }
7501 
7502 
7504  if (IsGlobalObject()) return this;
7505 
7506  // Make sure prototypes are fast objects and their maps have the bit set
7507  // so they remain fast.
7508  Map* proto_map = map();
7509  if (!proto_map->used_for_prototype()) {
7510  if (!HasFastProperties()) {
7511  MaybeObject* new_proto = TransformToFastProperties(0);
7512  if (new_proto->IsFailure()) return new_proto;
7513  ASSERT(new_proto == this);
7514  proto_map = map();
7515  if (!proto_map->is_shared()) {
7516  proto_map->set_used_for_prototype(true);
7517  }
7518  } else {
7519  Heap* heap = GetHeap();
7520  // We use the hole value as a singleton key in the prototype transition
7521  // map so that we don't multiply the number of maps unnecessarily.
7522  Map* new_map =
7523  proto_map->GetPrototypeTransition(heap->the_hole_value());
7524  if (new_map == NULL) {
7525  MaybeObject* maybe_new_map =
7527  if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map;
7528  new_map->set_used_for_prototype(true);
7529  MaybeObject* ok =
7530  proto_map->PutPrototypeTransition(heap->the_hole_value(),
7531  new_map);
7532  if (ok->IsFailure()) return ok;
7533  }
7534  ASSERT(!proto_map->is_shared() && !new_map->is_shared());
7535  set_map(new_map);
7536  }
7537  }
7538  return this;
7539 }
7540 
7541 
7543  ASSERT(value->IsJSReceiver());
7544  Heap* heap = GetHeap();
7545 
7546  // First some logic for the map of the prototype to make sure the
7547  // used_for_prototype flag is set.
7548  if (value->IsJSObject()) {
7549  MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
7550  if (ok->IsFailure()) return ok;
7551  }
7552 
7553  // Now some logic for the maps of the objects that are created by using this
7554  // function as a constructor.
7555  if (has_initial_map()) {
7556  // If the function has allocated the initial map
7557  // replace it with a copy containing the new prototype.
7558  Map* new_map;
7559  MaybeObject* maybe_new_map =
7561  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7562  new_map->set_prototype(value);
7563  MaybeObject* maybe_object =
7565  if (maybe_object->IsFailure()) return maybe_object;
7566  } else {
7567  // Put the value in the initial map field until an initial map is
7568  // needed. At that point, a new initial map is created and the
7569  // prototype is put into the initial map where it belongs.
7570  set_prototype_or_initial_map(value);
7571  }
7572  heap->ClearInstanceofCache();
7573  return value;
7574 }
7575 
7576 
7577 MaybeObject* JSFunction::SetPrototype(Object* value) {
7579  Object* construct_prototype = value;
7580 
7581  // If the value is not a JSReceiver, store the value in the map's
7582  // constructor field so it can be accessed. Also, set the prototype
7583  // used for constructing objects to the original object prototype.
7584  // See ECMA-262 13.2.2.
7585  if (!value->IsJSReceiver()) {
7586  // Copy the map so this does not affect unrelated functions.
7587  // Remove map transitions because they point to maps with a
7588  // different prototype.
7589  Map* new_map;
7590  { MaybeObject* maybe_new_map =
7592  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7593  }
7594  Heap* heap = new_map->GetHeap();
7595  set_map(new_map);
7596  new_map->set_constructor(value);
7597  new_map->set_non_instance_prototype(true);
7598  construct_prototype =
7599  heap->isolate()->context()->global_context()->
7600  initial_object_prototype();
7601  } else {
7602  map()->set_non_instance_prototype(false);
7603  }
7604 
7605  return SetInstancePrototype(construct_prototype);
7606 }
7607 
7608 
7610  Context* global_context = context()->global_context();
7611  Map* no_prototype_map = shared()->is_classic_mode()
7612  ? global_context->function_without_prototype_map()
7613  : global_context->strict_mode_function_without_prototype_map();
7614 
7615  if (map() == no_prototype_map) {
7616  // Be idempotent.
7617  return this;
7618  }
7619 
7620  ASSERT(map() == (shared()->is_classic_mode()
7621  ? global_context->function_map()
7622  : global_context->strict_mode_function_map()));
7623 
7624  set_map(no_prototype_map);
7625  set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
7626  return this;
7627 }
7628 
7629 
7631  shared()->set_instance_class_name(name);
7632  return this;
7633 }
7634 
7635 
7636 void JSFunction::PrintName(FILE* out) {
7637  SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
7638  PrintF(out, "%s", *name);
7639 }
7640 
7641 
7644 }
7645 
7646 
7647 MaybeObject* Oddball::Initialize(const char* to_string,
7648  Object* to_number,
7649  byte kind) {
7650  String* symbol;
7651  { MaybeObject* maybe_symbol =
7652  Isolate::Current()->heap()->LookupAsciiSymbol(to_string);
7653  if (!maybe_symbol->To(&symbol)) return maybe_symbol;
7654  }
7655  set_to_string(symbol);
7656  set_to_number(to_number);
7657  set_kind(kind);
7658  return this;
7659 }
7660 
7661 
7663  Object* n = name();
7664  if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
7665  return String::cast(n);
7666 }
7667 
7668 
7670  return !script()->IsUndefined() &&
7671  !reinterpret_cast<Script*>(script())->source()->IsUndefined();
7672 }
7673 
7674 
7676  if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
7677  Handle<String> source(String::cast(Script::cast(script())->source()));
7678  return SubString(source, start_position(), end_position());
7679 }
7680 
7681 
7683  return end_position() - start_position();
7684 }
7685 
7686 
7688  int instance_size =
7691  if (instance_size > JSObject::kMaxInstanceSize) {
7692  instance_size = JSObject::kMaxInstanceSize;
7693  }
7694  return instance_size;
7695 }
7696 
7697 
7700 }
7701 
7702 
7704  // Check the basic conditions for generating inline constructor code.
7705  if (!FLAG_inline_new
7707  || this_property_assignments_count() == 0) {
7708  return false;
7709  }
7710 
7711  // If the prototype is null inline constructors cause no problems.
7712  if (!prototype->IsJSObject()) {
7713  ASSERT(prototype->IsNull());
7714  return true;
7715  }
7716 
7717  Heap* heap = GetHeap();
7718 
7719  // Traverse the proposed prototype chain looking for setters for properties of
7720  // the same names as are set by the inline constructor.
7721  for (Object* obj = prototype;
7722  obj != heap->null_value();
7723  obj = obj->GetPrototype()) {
7724  JSObject* js_object = JSObject::cast(obj);
7725  for (int i = 0; i < this_property_assignments_count(); i++) {
7726  LookupResult result(heap->isolate());
7728  js_object->LocalLookupRealNamedProperty(name, &result);
7729  if (result.IsFound() && result.type() == CALLBACKS) {
7730  return false;
7731  }
7732  }
7733  }
7734 
7735  return true;
7736 }
7737 
7738 
7742  false));
7743 }
7744 
7745 
7747  bool only_simple_this_property_assignments,
7748  FixedArray* assignments) {
7751  only_simple_this_property_assignments));
7752  set_this_property_assignments(assignments);
7753  set_this_property_assignments_count(assignments->length() / 3);
7754 }
7755 
7756 
7758  Heap* heap = GetHeap();
7761  false));
7762  set_this_property_assignments(heap->undefined_value());
7764 }
7765 
7766 
7769  ASSERT(obj->IsFixedArray());
7771  obj = FixedArray::cast(obj)->get(index * 3);
7772  ASSERT(obj->IsString());
7773  return String::cast(obj);
7774 }
7775 
7776 
7779  ASSERT(obj->IsFixedArray());
7781  obj = FixedArray::cast(obj)->get(index * 3 + 1);
7782  return Smi::cast(obj)->value() != -1;
7783 }
7784 
7785 
7788  Object* obj =
7789  FixedArray::cast(this_property_assignments())->get(index * 3 + 1);
7790  return Smi::cast(obj)->value();
7791 }
7792 
7793 
7796  Object* obj =
7797  FixedArray::cast(this_property_assignments())->get(index * 3 + 2);
7798  return obj;
7799 }
7800 
7801 
7802 // Support function for printing the source code to a StringStream
7803 // without any allocation in the heap.
7805  int max_length) {
7806  // For some native functions there is no source.
7807  if (!HasSourceCode()) {
7808  accumulator->Add("<No Source>");
7809  return;
7810  }
7811 
7812  // Get the source for the script which this function came from.
7813  // Don't use String::cast because we don't want more assertion errors while
7814  // we are already creating a stack dump.
7815  String* script_source =
7816  reinterpret_cast<String*>(Script::cast(script())->source());
7817 
7818  if (!script_source->LooksValid()) {
7819  accumulator->Add("<Invalid Source>");
7820  return;
7821  }
7822 
7823  if (!is_toplevel()) {
7824  accumulator->Add("function ");
7825  Object* name = this->name();
7826  if (name->IsString() && String::cast(name)->length() > 0) {
7827  accumulator->PrintName(name);
7828  }
7829  }
7830 
7831  int len = end_position() - start_position();
7832  if (len <= max_length || max_length < 0) {
7833  accumulator->Put(script_source, start_position(), end_position());
7834  } else {
7835  accumulator->Put(script_source,
7836  start_position(),
7837  start_position() + max_length);
7838  accumulator->Add("...\n");
7839  }
7840 }
7841 
7842 
7843 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
7844  if (code->instruction_size() != recompiled->instruction_size()) return false;
7845  ByteArray* code_relocation = code->relocation_info();
7846  ByteArray* recompiled_relocation = recompiled->relocation_info();
7847  int length = code_relocation->length();
7848  if (length != recompiled_relocation->length()) return false;
7849  int compare = memcmp(code_relocation->GetDataStartAddress(),
7850  recompiled_relocation->GetDataStartAddress(),
7851  length);
7852  return compare == 0;
7853 }
7854 
7855 
7858  AssertNoAllocation no_allocation;
7859  Code* code = this->code();
7860  if (IsCodeEquivalent(code, recompiled)) {
7861  // Copy the deoptimization data from the recompiled code.
7862  code->set_deoptimization_data(recompiled->deoptimization_data());
7863  code->set_has_deoptimization_support(true);
7864  } else {
7865  // TODO(3025757): In case the recompiled isn't equivalent to the
7866  // old code, we have to replace it. We should try to avoid this
7867  // altogether because it flushes valuable type feedback by
7868  // effectively resetting all IC state.
7869  set_code(recompiled);
7870  }
7872 }
7873 
7874 
7876  // Disable optimization for the shared function info and mark the
7877  // code as non-optimizable. The marker on the shared function info
7878  // is there because we flush non-optimized code thereby loosing the
7879  // non-optimizable information for the code. When the code is
7880  // regenerated and set on the shared function info it is marked as
7881  // non-optimizable if optimization is disabled for the shared
7882  // function info.
7883  set_optimization_disabled(true);
7884  // Code should be the lazy compilation stub or else unoptimized. If the
7885  // latter, disable optimization for the code too.
7886  ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
7887  if (code()->kind() == Code::FUNCTION) {
7888  code()->set_optimizable(false);
7889  }
7890  if (FLAG_trace_opt) {
7891  PrintF("[disabled optimization for %s]\n", *DebugName()->ToCString());
7892  }
7893 }
7894 
7895 
7897  ASSERT(id != AstNode::kNoNumber);
7898  Code* unoptimized = code();
7899  DeoptimizationOutputData* data =
7900  DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
7901  unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
7902  USE(ignore);
7903  return true; // Return true if there was no ASSERT.
7904 }
7905 
7906 
7909 
7910  if (!FLAG_clever_optimizations) return;
7911 
7912  // Only initiate the tracking the first time.
7913  if (live_objects_may_exist()) return;
7914  set_live_objects_may_exist(true);
7915 
7916  // No tracking during the snapshot construction phase.
7917  if (Serializer::enabled()) return;
7918 
7919  if (map->unused_property_fields() == 0) return;
7920 
7921  // Nonzero counter is a leftover from the previous attempt interrupted
7922  // by GC, keep it.
7923  if (construction_count() == 0) {
7925  }
7926  set_initial_map(map);
7927  Builtins* builtins = map->GetHeap()->isolate()->builtins();
7928  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
7929  construct_stub());
7930  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
7931 }
7932 
7933 
7934 // Called from GC, hence reinterpret_cast and unchecked accessors.
7936  Map* map = reinterpret_cast<Map*>(initial_map());
7937 
7938  // Make the map remember to restore the link if it survives the GC.
7939  map->set_bit_field2(
7941 
7942  // Undo state changes made by StartInobjectTracking (except the
7943  // construction_count). This way if the initial map does not survive the GC
7944  // then StartInobjectTracking will be called again the next time the
7945  // constructor is called. The countdown will continue and (possibly after
7946  // several more GCs) CompleteInobjectSlackTracking will eventually be called.
7947  Heap* heap = map->GetHeap();
7948  set_initial_map(heap->raw_unchecked_undefined_value());
7949  Builtins* builtins = heap->isolate()->builtins();
7950  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
7951  *RawField(this, kConstructStubOffset));
7952  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
7953  // It is safe to clear the flag: it will be set again if the map is live.
7954  set_live_objects_may_exist(false);
7955 }
7956 
7957 
7958 // Called from GC, hence reinterpret_cast and unchecked accessors.
7960  map->set_bit_field2(
7962 
7963  // Resume inobject slack tracking.
7964  set_initial_map(map);
7965  Builtins* builtins = map->GetHeap()->isolate()->builtins();
7966  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
7967  *RawField(this, kConstructStubOffset));
7968  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
7969  // The map survived the gc, so there may be objects referencing it.
7970  set_live_objects_may_exist(true);
7971 }
7972 
7973 
7975  code()->ClearInlineCaches();
7976  set_ic_age(new_ic_age);
7977  if (code()->kind() == Code::FUNCTION) {
7978  code()->set_profiler_ticks(0);
7979  if (optimization_disabled() &&
7981  // Re-enable optimizations if they were disabled due to opt_count limit.
7982  set_optimization_disabled(false);
7983  code()->set_optimizable(true);
7984  }
7985  set_opt_count(0);
7986  set_deopt_count(0);
7987  }
7988 }
7989 
7990 
7991 static void GetMinInobjectSlack(Map* map, void* data) {
7992  int slack = map->unused_property_fields();
7993  if (*reinterpret_cast<int*>(data) > slack) {
7994  *reinterpret_cast<int*>(data) = slack;
7995  }
7996 }
7997 
7998 
7999 static void ShrinkInstanceSize(Map* map, void* data) {
8000  int slack = *reinterpret_cast<int*>(data);
8001  map->set_inobject_properties(map->inobject_properties() - slack);
8002  map->set_unused_property_fields(map->unused_property_fields() - slack);
8003  map->set_instance_size(map->instance_size() - slack * kPointerSize);
8004 
8005  // Visitor id might depend on the instance size, recalculate it.
8006  map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
8007 }
8008 
8009 
8011  ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress());
8012  Map* map = Map::cast(initial_map());
8013 
8014  Heap* heap = map->GetHeap();
8015  set_initial_map(heap->undefined_value());
8016  Builtins* builtins = heap->isolate()->builtins();
8017  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
8018  construct_stub());
8019  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
8020 
8021  int slack = map->unused_property_fields();
8022  map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
8023  if (slack != 0) {
8024  // Resize the initial map and all maps in its transition tree.
8025  map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
8026 
8027  // Give the correct expected_nof_properties to initial maps created later.
8028  ASSERT(expected_nof_properties() >= slack);
8030  }
8031 }
8032 
8033 
8035  v->VisitSharedFunctionInfo(this);
8037 }
8038 
8039 
8040 #define DECLARE_TAG(ignore1, name, ignore2) name,
8041 const char* const VisitorSynchronization::kTags[
8044 };
8045 #undef DECLARE_TAG
8046 
8047 
8048 #define DECLARE_TAG(ignore1, ignore2, name) name,
8049 const char* const VisitorSynchronization::kTagNames[
8052 };
8053 #undef DECLARE_TAG
8054 
8055 
8056 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
8057  ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
8058  Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
8059  Object* old_target = target;
8060  VisitPointer(&target);
8061  CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target.
8062 }
8063 
8064 
8065 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
8066  Object* code = Code::GetObjectFromEntryAddress(entry_address);
8067  Object* old_code = code;
8068  VisitPointer(&code);
8069  if (code != old_code) {
8070  Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
8071  }
8072 }
8073 
8074 
8075 void ObjectVisitor::VisitGlobalPropertyCell(RelocInfo* rinfo) {
8076  ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
8077  Object* cell = rinfo->target_cell();
8078  Object* old_cell = cell;
8079  VisitPointer(&cell);
8080  if (cell != old_cell) {
8081  rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell));
8082  }
8083 }
8084 
8085 
8086 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
8087  ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
8088  rinfo->IsPatchedReturnSequence()) ||
8089  (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
8090  rinfo->IsPatchedDebugBreakSlotSequence()));
8091  Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
8092  Object* old_target = target;
8093  VisitPointer(&target);
8094  CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target.
8095 }
8096 
8097 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
8098  ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
8099  VisitPointer(rinfo->target_object_address());
8100 }
8101 
8102 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
8103  Address* p = rinfo->target_reference_address();
8104  VisitExternalReferences(p, p + 1);
8105 }
8106 
8108  set_relocation_info(GetHeap()->empty_byte_array());
8109 }
8110 
8111 
8112 void Code::Relocate(intptr_t delta) {
8113  for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
8114  it.rinfo()->apply(delta);
8115  }
8117 }
8118 
8119 
8120 void Code::CopyFrom(const CodeDesc& desc) {
8121  ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT);
8122 
8123  // copy code
8124  memmove(instruction_start(), desc.buffer, desc.instr_size);
8125 
8126  // copy reloc info
8127  memmove(relocation_start(),
8128  desc.buffer + desc.buffer_size - desc.reloc_size,
8129  desc.reloc_size);
8130 
8131  // unbox handles and relocate
8132  intptr_t delta = instruction_start() - desc.buffer;
8133  int mode_mask = RelocInfo::kCodeTargetMask |
8134  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
8135  RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
8136  RelocInfo::kApplyMask;
8137  Assembler* origin = desc.origin; // Needed to find target_object on X64.
8138  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
8139  RelocInfo::Mode mode = it.rinfo()->rmode();
8140  if (mode == RelocInfo::EMBEDDED_OBJECT) {
8141  Handle<Object> p = it.rinfo()->target_object_handle(origin);
8142  it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER);
8143  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
8144  Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle();
8145  it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER);
8146  } else if (RelocInfo::IsCodeTarget(mode)) {
8147  // rewrite code handles in inline cache targets to direct
8148  // pointers to the first instruction in the code object
8149  Handle<Object> p = it.rinfo()->target_object_handle(origin);
8150  Code* code = Code::cast(*p);
8151  it.rinfo()->set_target_address(code->instruction_start(),
8153  } else {
8154  it.rinfo()->apply(delta);
8155  }
8156  }
8158 }
8159 
8160 
8161 // Locate the source position which is closest to the address in the code. This
8162 // is using the source position information embedded in the relocation info.
8163 // The position returned is relative to the beginning of the script where the
8164 // source for this function is found.
8166  int distance = kMaxInt;
8167  int position = RelocInfo::kNoPosition; // Initially no position found.
8168  // Run through all the relocation info to find the best matching source
8169  // position. All the code needs to be considered as the sequence of the
8170  // instructions in the code does not necessarily follow the same order as the
8171  // source.
8172  RelocIterator it(this, RelocInfo::kPositionMask);
8173  while (!it.done()) {
8174  // Only look at positions after the current pc.
8175  if (it.rinfo()->pc() < pc) {
8176  // Get position and distance.
8177 
8178  int dist = static_cast<int>(pc - it.rinfo()->pc());
8179  int pos = static_cast<int>(it.rinfo()->data());
8180  // If this position is closer than the current candidate or if it has the
8181  // same distance as the current candidate and the position is higher then
8182  // this position is the new candidate.
8183  if ((dist < distance) ||
8184  (dist == distance && pos > position)) {
8185  position = pos;
8186  distance = dist;
8187  }
8188  }
8189  it.next();
8190  }
8191  return position;
8192 }
8193 
8194 
8195 // Same as Code::SourcePosition above except it only looks for statement
8196 // positions.
8198  // First find the position as close as possible using all position
8199  // information.
8200  int position = SourcePosition(pc);
8201  // Now find the closest statement position before the position.
8202  int statement_position = 0;
8203  RelocIterator it(this, RelocInfo::kPositionMask);
8204  while (!it.done()) {
8205  if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
8206  int p = static_cast<int>(it.rinfo()->data());
8207  if (statement_position < p && p <= position) {
8208  statement_position = p;
8209  }
8210  }
8211  it.next();
8212  }
8213  return statement_position;
8214 }
8215 
8216 
8218  SafepointTable table(this);
8219  return table.FindEntry(pc);
8220 }
8221 
8222 
8224  // Indicate the absence of a stack-check table by a table start after the
8225  // end of the instructions. Table start must be aligned, so round up.
8227 }
8228 
8229 
8232  AssertNoAllocation no_allocation;
8233  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
8234  for (RelocIterator it(this, mask); !it.done(); it.next()) {
8235  RelocInfo* info = it.rinfo();
8236  Object* object = info->target_object();
8237  if (object->IsMap()) return Map::cast(object);
8238  }
8239  return NULL;
8240 }
8241 
8242 
8244  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
8245  RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
8246  RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
8247  RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
8248  for (RelocIterator it(this, mask); !it.done(); it.next()) {
8249  RelocInfo* info = it.rinfo();
8250  Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
8251  if (target->is_inline_cache_stub()) {
8252  IC::Clear(info->pc());
8253  }
8254  }
8255 }
8256 
8257 
8259  Object* raw_info = type_feedback_info();
8260  if (raw_info->IsTypeFeedbackInfo()) {
8262  TypeFeedbackInfo::cast(raw_info)->type_feedback_cells();
8263  for (int i = 0; i < type_feedback_cells->CellCount(); i++) {
8264  ASSERT(type_feedback_cells->AstId(i)->IsSmi());
8265  JSGlobalPropertyCell* cell = type_feedback_cells->Cell(i);
8266  cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap));
8267  }
8268  }
8269 }
8270 
8271 
8274 }
8275 
8276 
8277 #ifdef ENABLE_DISASSEMBLER
8278 
8279 void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
8280  disasm::NameConverter converter;
8281  int deopt_count = DeoptCount();
8282  PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
8283  if (0 == deopt_count) return;
8284 
8285  PrintF(out, "%6s %6s %6s %6s %12s\n", "index", "ast id", "argc", "pc",
8286  FLAG_print_code_verbose ? "commands" : "");
8287  for (int i = 0; i < deopt_count; i++) {
8288  PrintF(out, "%6d %6d %6d %6d",
8289  i,
8290  AstId(i)->value(),
8291  ArgumentsStackHeight(i)->value(),
8292  Pc(i)->value());
8293 
8294  if (!FLAG_print_code_verbose) {
8295  PrintF(out, "\n");
8296  continue;
8297  }
8298  // Print details of the frame translation.
8299  int translation_index = TranslationIndex(i)->value();
8300  TranslationIterator iterator(TranslationByteArray(), translation_index);
8301  Translation::Opcode opcode =
8302  static_cast<Translation::Opcode>(iterator.Next());
8303  ASSERT(Translation::BEGIN == opcode);
8304  int frame_count = iterator.Next();
8305  int jsframe_count = iterator.Next();
8306  PrintF(out, " %s {frame count=%d, js frame count=%d}\n",
8307  Translation::StringFor(opcode),
8308  frame_count,
8309  jsframe_count);
8310 
8311  while (iterator.HasNext() &&
8312  Translation::BEGIN !=
8313  (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
8314  PrintF(out, "%24s %s ", "", Translation::StringFor(opcode));
8315 
8316  switch (opcode) {
8317  case Translation::BEGIN:
8318  UNREACHABLE();
8319  break;
8320 
8321  case Translation::JS_FRAME: {
8322  int ast_id = iterator.Next();
8323  int function_id = iterator.Next();
8324  JSFunction* function =
8325  JSFunction::cast(LiteralArray()->get(function_id));
8326  unsigned height = iterator.Next();
8327  PrintF(out, "{ast_id=%d, function=", ast_id);
8328  function->PrintName(out);
8329  PrintF(out, ", height=%u}", height);
8330  break;
8331  }
8332 
8333  case Translation::ARGUMENTS_ADAPTOR_FRAME:
8334  case Translation::CONSTRUCT_STUB_FRAME: {
8335  int function_id = iterator.Next();
8336  JSFunction* function =
8337  JSFunction::cast(LiteralArray()->get(function_id));
8338  unsigned height = iterator.Next();
8339  PrintF(out, "{function=");
8340  function->PrintName(out);
8341  PrintF(out, ", height=%u}", height);
8342  break;
8343  }
8344 
8345  case Translation::DUPLICATE:
8346  break;
8347 
8348  case Translation::REGISTER: {
8349  int reg_code = iterator.Next();
8350  PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
8351  break;
8352  }
8353 
8354  case Translation::INT32_REGISTER: {
8355  int reg_code = iterator.Next();
8356  PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
8357  break;
8358  }
8359 
8360  case Translation::DOUBLE_REGISTER: {
8361  int reg_code = iterator.Next();
8362  PrintF(out, "{input=%s}",
8364  break;
8365  }
8366 
8367  case Translation::STACK_SLOT: {
8368  int input_slot_index = iterator.Next();
8369  PrintF(out, "{input=%d}", input_slot_index);
8370  break;
8371  }
8372 
8373  case Translation::INT32_STACK_SLOT: {
8374  int input_slot_index = iterator.Next();
8375  PrintF(out, "{input=%d}", input_slot_index);
8376  break;
8377  }
8378 
8379  case Translation::DOUBLE_STACK_SLOT: {
8380  int input_slot_index = iterator.Next();
8381  PrintF(out, "{input=%d}", input_slot_index);
8382  break;
8383  }
8384 
8385  case Translation::LITERAL: {
8386  unsigned literal_index = iterator.Next();
8387  PrintF(out, "{literal_id=%u}", literal_index);
8388  break;
8389  }
8390 
8391  case Translation::ARGUMENTS_OBJECT:
8392  break;
8393  }
8394  PrintF(out, "\n");
8395  }
8396  }
8397 }
8398 
8399 
8400 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
8401  PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
8402  this->DeoptPoints());
8403  if (this->DeoptPoints() == 0) return;
8404 
8405  PrintF("%6s %8s %s\n", "ast id", "pc", "state");
8406  for (int i = 0; i < this->DeoptPoints(); i++) {
8407  int pc_and_state = this->PcAndState(i)->value();
8408  PrintF("%6d %8d %s\n",
8409  this->AstId(i)->value(),
8410  FullCodeGenerator::PcField::decode(pc_and_state),
8412  FullCodeGenerator::StateField::decode(pc_and_state)));
8413  }
8414 }
8415 
8416 
8417 // Identify kind of code.
8418 const char* Code::Kind2String(Kind kind) {
8419  switch (kind) {
8420  case FUNCTION: return "FUNCTION";
8421  case OPTIMIZED_FUNCTION: return "OPTIMIZED_FUNCTION";
8422  case STUB: return "STUB";
8423  case BUILTIN: return "BUILTIN";
8424  case LOAD_IC: return "LOAD_IC";
8425  case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
8426  case STORE_IC: return "STORE_IC";
8427  case KEYED_STORE_IC: return "KEYED_STORE_IC";
8428  case CALL_IC: return "CALL_IC";
8429  case KEYED_CALL_IC: return "KEYED_CALL_IC";
8430  case UNARY_OP_IC: return "UNARY_OP_IC";
8431  case BINARY_OP_IC: return "BINARY_OP_IC";
8432  case COMPARE_IC: return "COMPARE_IC";
8433  case TO_BOOLEAN_IC: return "TO_BOOLEAN_IC";
8434  }
8435  UNREACHABLE();
8436  return NULL;
8437 }
8438 
8439 
8440 const char* Code::ICState2String(InlineCacheState state) {
8441  switch (state) {
8442  case UNINITIALIZED: return "UNINITIALIZED";
8443  case PREMONOMORPHIC: return "PREMONOMORPHIC";
8444  case MONOMORPHIC: return "MONOMORPHIC";
8445  case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
8446  case MEGAMORPHIC: return "MEGAMORPHIC";
8447  case DEBUG_BREAK: return "DEBUG_BREAK";
8448  case DEBUG_PREPARE_STEP_IN: return "DEBUG_PREPARE_STEP_IN";
8449  }
8450  UNREACHABLE();
8451  return NULL;
8452 }
8453 
8454 
8455 const char* Code::PropertyType2String(PropertyType type) {
8456  switch (type) {
8457  case NORMAL: return "NORMAL";
8458  case FIELD: return "FIELD";
8459  case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
8460  case CALLBACKS: return "CALLBACKS";
8461  case HANDLER: return "HANDLER";
8462  case INTERCEPTOR: return "INTERCEPTOR";
8463  case MAP_TRANSITION: return "MAP_TRANSITION";
8464  case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
8465  case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
8466  }
8467  UNREACHABLE(); // keep the compiler happy
8468  return NULL;
8469 }
8470 
8471 
8472 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
8473  const char* name = NULL;
8474  switch (kind) {
8475  case CALL_IC:
8476  if (extra == STRING_INDEX_OUT_OF_BOUNDS) {
8477  name = "STRING_INDEX_OUT_OF_BOUNDS";
8478  }
8479  break;
8480  case STORE_IC:
8481  case KEYED_STORE_IC:
8482  if (extra == kStrictMode) {
8483  name = "STRICT";
8484  }
8485  break;
8486  default:
8487  break;
8488  }
8489  if (name != NULL) {
8490  PrintF(out, "extra_ic_state = %s\n", name);
8491  } else {
8492  PrintF(out, "extra_ic_state = %d\n", extra);
8493  }
8494 }
8495 
8496 
8497 void Code::Disassemble(const char* name, FILE* out) {
8498  PrintF(out, "kind = %s\n", Kind2String(kind()));
8499  if (is_inline_cache_stub()) {
8500  PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
8501  PrintExtraICState(out, kind(), extra_ic_state());
8502  if (ic_state() == MONOMORPHIC) {
8503  PrintF(out, "type = %s\n", PropertyType2String(type()));
8504  }
8505  if (is_call_stub() || is_keyed_call_stub()) {
8506  PrintF(out, "argc = %d\n", arguments_count());
8507  }
8508  if (is_compare_ic_stub()) {
8510  PrintF(out, "compare_state = %s\n", CompareIC::GetStateName(state));
8511  }
8512  if (is_compare_ic_stub() && major_key() == CodeStub::CompareIC) {
8514  PrintF(out, "compare_operation = %s\n", Token::Name(op));
8515  }
8516  }
8517  if ((name != NULL) && (name[0] != '\0')) {
8518  PrintF(out, "name = %s\n", name);
8519  }
8520  if (kind() == OPTIMIZED_FUNCTION) {
8521  PrintF(out, "stack_slots = %d\n", stack_slots());
8522  }
8523 
8524  PrintF(out, "Instructions (size = %d)\n", instruction_size());
8525  Disassembler::Decode(out, this);
8526  PrintF(out, "\n");
8527 
8528  if (kind() == FUNCTION) {
8529  DeoptimizationOutputData* data =
8530  DeoptimizationOutputData::cast(this->deoptimization_data());
8531  data->DeoptimizationOutputDataPrint(out);
8532  } else if (kind() == OPTIMIZED_FUNCTION) {
8533  DeoptimizationInputData* data =
8534  DeoptimizationInputData::cast(this->deoptimization_data());
8535  data->DeoptimizationInputDataPrint(out);
8536  }
8537  PrintF("\n");
8538 
8539  if (kind() == OPTIMIZED_FUNCTION) {
8540  SafepointTable table(this);
8541  PrintF(out, "Safepoints (size = %u)\n", table.size());
8542  for (unsigned i = 0; i < table.length(); i++) {
8543  unsigned pc_offset = table.GetPcOffset(i);
8544  PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset);
8545  table.PrintEntry(i);
8546  PrintF(out, " (sp -> fp)");
8547  SafepointEntry entry = table.GetEntry(i);
8548  if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
8549  PrintF(out, " %6d", entry.deoptimization_index());
8550  } else {
8551  PrintF(out, " <none>");
8552  }
8553  if (entry.argument_count() > 0) {
8554  PrintF(out, " argc: %d", entry.argument_count());
8555  }
8556  PrintF(out, "\n");
8557  }
8558  PrintF(out, "\n");
8559  } else if (kind() == FUNCTION) {
8560  unsigned offset = stack_check_table_offset();
8561  // If there is no stack check table, the "table start" will at or after
8562  // (due to alignment) the end of the instruction stream.
8563  if (static_cast<int>(offset) < instruction_size()) {
8564  unsigned* address =
8565  reinterpret_cast<unsigned*>(instruction_start() + offset);
8566  unsigned length = address[0];
8567  PrintF(out, "Stack checks (size = %u)\n", length);
8568  PrintF(out, "ast_id pc_offset\n");
8569  for (unsigned i = 0; i < length; ++i) {
8570  unsigned index = (2 * i) + 1;
8571  PrintF(out, "%6u %9u\n", address[index], address[index + 1]);
8572  }
8573  PrintF(out, "\n");
8574  }
8575  }
8576 
8577  PrintF("RelocInfo (size = %d)\n", relocation_size());
8578  for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
8579  PrintF(out, "\n");
8580 }
8581 #endif // ENABLE_DISASSEMBLER
8582 
8583 
8585  int capacity,
8586  int length,
8587  SetFastElementsCapacitySmiMode smi_mode) {
8588  Heap* heap = GetHeap();
8589  // We should never end in here with a pixel or external array.
8591 
8592  // Allocate a new fast elements backing store.
8593  FixedArray* new_elements;
8594  { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
8595  if (!maybe->To(&new_elements)) return maybe;
8596  }
8597 
8598  ElementsKind elements_kind = GetElementsKind();
8599  ElementsKind new_elements_kind;
8600  // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
8601  // or if it's allowed and the old elements array contained only SMIs.
8602  bool has_fast_smi_elements =
8603  (smi_mode == kForceSmiElements) ||
8604  ((smi_mode == kAllowSmiElements) && HasFastSmiElements());
8605  if (has_fast_smi_elements) {
8606  if (IsHoleyElementsKind(elements_kind)) {
8607  new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
8608  } else {
8609  new_elements_kind = FAST_SMI_ELEMENTS;
8610  }
8611  } else {
8612  if (IsHoleyElementsKind(elements_kind)) {
8613  new_elements_kind = FAST_HOLEY_ELEMENTS;
8614  } else {
8615  new_elements_kind = FAST_ELEMENTS;
8616  }
8617  }
8618  FixedArrayBase* old_elements = elements();
8619  ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8620  { MaybeObject* maybe_obj =
8621  accessor->CopyElements(this, new_elements, new_elements_kind);
8622  if (maybe_obj->IsFailure()) return maybe_obj;
8623  }
8624  if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8625  Map* new_map = map();
8626  if (new_elements_kind != elements_kind) {
8627  MaybeObject* maybe =
8628  GetElementsTransitionMap(GetIsolate(), new_elements_kind);
8629  if (!maybe->To(&new_map)) return maybe;
8630  }
8631  ValidateElements();
8632  set_map_and_elements(new_map, new_elements);
8633  } else {
8634  FixedArray* parameter_map = FixedArray::cast(old_elements);
8635  parameter_map->set(1, new_elements);
8636  }
8637 
8638  if (FLAG_trace_elements_transitions) {
8639  PrintElementsTransition(stdout, elements_kind, old_elements,
8640  GetElementsKind(), new_elements);
8641  }
8642 
8643  if (IsJSArray()) {
8644  JSArray::cast(this)->set_length(Smi::FromInt(length));
8645  }
8646  return new_elements;
8647 }
8648 
8649 
8651  int capacity,
8652  int length) {
8653  Heap* heap = GetHeap();
8654  // We should never end in here with a pixel or external array.
8656 
8657  FixedArrayBase* elems;
8658  { MaybeObject* maybe_obj =
8659  heap->AllocateUninitializedFixedDoubleArray(capacity);
8660  if (!maybe_obj->To(&elems)) return maybe_obj;
8661  }
8662 
8663  ElementsKind elements_kind = GetElementsKind();
8664  ElementsKind new_elements_kind = elements_kind;
8665  if (IsHoleyElementsKind(elements_kind)) {
8666  new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
8667  } else {
8668  new_elements_kind = FAST_DOUBLE_ELEMENTS;
8669  }
8670 
8671  Map* new_map;
8672  { MaybeObject* maybe_obj =
8673  GetElementsTransitionMap(heap->isolate(), new_elements_kind);
8674  if (!maybe_obj->To(&new_map)) return maybe_obj;
8675  }
8676 
8677  FixedArrayBase* old_elements = elements();
8678  ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8679  { MaybeObject* maybe_obj =
8680  accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS);
8681  if (maybe_obj->IsFailure()) return maybe_obj;
8682  }
8683  if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8684  ValidateElements();
8685  set_map_and_elements(new_map, elems);
8686  } else {
8687  FixedArray* parameter_map = FixedArray::cast(old_elements);
8688  parameter_map->set(1, elems);
8689  }
8690 
8691  if (FLAG_trace_elements_transitions) {
8692  PrintElementsTransition(stdout, elements_kind, old_elements,
8693  GetElementsKind(), elems);
8694  }
8695 
8696  if (IsJSArray()) {
8697  JSArray::cast(this)->set_length(Smi::FromInt(length));
8698  }
8699 
8700  return this;
8701 }
8702 
8703 
8704 MaybeObject* JSArray::Initialize(int capacity) {
8705  Heap* heap = GetHeap();
8706  ASSERT(capacity >= 0);
8708  FixedArray* new_elements;
8709  if (capacity == 0) {
8710  new_elements = heap->empty_fixed_array();
8711  } else {
8712  MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity);
8713  if (!maybe_obj->To(&new_elements)) return maybe_obj;
8714  }
8715  set_elements(new_elements);
8716  return this;
8717 }
8718 
8719 
8720 void JSArray::Expand(int required_size) {
8722  Handle<JSArray>(this), required_size, required_size);
8723 }
8724 
8725 
8727  // We should never end in here with a pixel or external array.
8729  return GetElementsAccessor()->SetLength(this, len);
8730 }
8731 
8732 
8734  FixedArray* cache = prototype_transitions();
8735  int number_of_transitions = NumberOfProtoTransitions();
8736  const int proto_offset =
8738  const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
8739  const int step = kProtoTransitionElementsPerEntry;
8740  for (int i = 0; i < number_of_transitions; i++) {
8741  if (cache->get(proto_offset + i * step) == prototype) {
8742  Object* map = cache->get(map_offset + i * step);
8743  return Map::cast(map);
8744  }
8745  }
8746  return NULL;
8747 }
8748 
8749 
8750 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
8751  ASSERT(map->IsMap());
8752  ASSERT(HeapObject::cast(prototype)->map()->IsMap());
8753  // Don't cache prototype transition if this map is shared.
8754  if (is_shared() || !FLAG_cache_prototype_transitions) return this;
8755 
8756  FixedArray* cache = prototype_transitions();
8757 
8758  const int step = kProtoTransitionElementsPerEntry;
8759  const int header = kProtoTransitionHeaderSize;
8760 
8761  int capacity = (cache->length() - header) / step;
8762 
8763  int transitions = NumberOfProtoTransitions() + 1;
8764 
8765  if (transitions > capacity) {
8766  if (capacity > kMaxCachedPrototypeTransitions) return this;
8767 
8768  FixedArray* new_cache;
8769  // Grow array by factor 2 over and above what we need.
8770  { MaybeObject* maybe_cache =
8771  GetHeap()->AllocateFixedArray(transitions * 2 * step + header);
8772  if (!maybe_cache->To(&new_cache)) return maybe_cache;
8773  }
8774 
8775  for (int i = 0; i < capacity * step; i++) {
8776  new_cache->set(i + header, cache->get(i + header));
8777  }
8778  cache = new_cache;
8779  set_prototype_transitions(cache);
8780  }
8781 
8782  int last = transitions - 1;
8783 
8784  cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype);
8785  cache->set(header + last * step + kProtoTransitionMapOffset, map);
8786  SetNumberOfProtoTransitions(transitions);
8787 
8788  return cache;
8789 }
8790 
8791 
8792 MaybeObject* JSReceiver::SetPrototype(Object* value,
8793  bool skip_hidden_prototypes) {
8794 #ifdef DEBUG
8795  int size = Size();
8796 #endif
8797 
8798  Heap* heap = GetHeap();
8799  // Silently ignore the change if value is not a JSObject or null.
8800  // SpiderMonkey behaves this way.
8801  if (!value->IsJSReceiver() && !value->IsNull()) return value;
8802 
8803  // From 8.6.2 Object Internal Methods
8804  // ...
8805  // In addition, if [[Extensible]] is false the value of the [[Class]] and
8806  // [[Prototype]] internal properties of the object may not be modified.
8807  // ...
8808  // Implementation specific extensions that modify [[Class]], [[Prototype]]
8809  // or [[Extensible]] must not violate the invariants defined in the preceding
8810  // paragraph.
8811  if (!this->map()->is_extensible()) {
8812  HandleScope scope(heap->isolate());
8813  Handle<Object> handle(this, heap->isolate());
8814  return heap->isolate()->Throw(
8815  *FACTORY->NewTypeError("non_extensible_proto",
8816  HandleVector<Object>(&handle, 1)));
8817  }
8818 
8819  // Before we can set the prototype we need to be sure
8820  // prototype cycles are prevented.
8821  // It is sufficient to validate that the receiver is not in the new prototype
8822  // chain.
8823  for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
8824  if (JSReceiver::cast(pt) == this) {
8825  // Cycle detected.
8826  HandleScope scope(heap->isolate());
8827  return heap->isolate()->Throw(
8828  *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
8829  }
8830  }
8831 
8832  JSReceiver* real_receiver = this;
8833 
8834  if (skip_hidden_prototypes) {
8835  // Find the first object in the chain whose prototype object is not
8836  // hidden and set the new prototype on that object.
8837  Object* current_proto = real_receiver->GetPrototype();
8838  while (current_proto->IsJSObject() &&
8839  JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) {
8840  real_receiver = JSReceiver::cast(current_proto);
8841  current_proto = current_proto->GetPrototype();
8842  }
8843  }
8844 
8845  // Set the new prototype of the object.
8846  Map* map = real_receiver->map();
8847 
8848  // Nothing to do if prototype is already set.
8849  if (map->prototype() == value) return value;
8850 
8851  if (value->IsJSObject()) {
8852  MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
8853  if (ok->IsFailure()) return ok;
8854  }
8855 
8856  Map* new_map = map->GetPrototypeTransition(value);
8857  if (new_map == NULL) {
8858  { MaybeObject* maybe_new_map =
8860  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
8861  }
8862 
8863  { MaybeObject* maybe_new_cache =
8864  map->PutPrototypeTransition(value, new_map);
8865  if (maybe_new_cache->IsFailure()) return maybe_new_cache;
8866  }
8867 
8868  new_map->set_prototype(value);
8869  }
8870  ASSERT(new_map->prototype() == value);
8871  real_receiver->set_map(new_map);
8872 
8873  heap->ClearInstanceofCache();
8874  ASSERT(size == Size());
8875  return value;
8876 }
8877 
8878 
8880  uint32_t first_arg,
8881  uint32_t arg_count,
8882  EnsureElementsMode mode) {
8883  // Elements in |Arguments| are ordered backwards (because they're on the
8884  // stack), but the method that's called here iterates over them in forward
8885  // direction.
8886  return EnsureCanContainElements(
8887  args->arguments() - first_arg - (arg_count - 1),
8888  arg_count, mode);
8889 }
8890 
8891 
8892 bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) {
8893  Isolate* isolate = GetIsolate();
8894  // Make sure that the top context does not change when doing
8895  // callbacks or interceptor calls.
8896  AssertNoContextChange ncc;
8897  HandleScope scope(isolate);
8899  Handle<JSReceiver> receiver_handle(receiver);
8900  Handle<JSObject> holder_handle(this);
8901  CustomArguments args(isolate, interceptor->data(), receiver, this);
8902  v8::AccessorInfo info(args.end());
8903  if (!interceptor->query()->IsUndefined()) {
8904  v8::IndexedPropertyQuery query =
8905  v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
8906  LOG(isolate,
8907  ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
8908  v8::Handle<v8::Integer> result;
8909  {
8910  // Leaving JavaScript.
8911  VMState state(isolate, EXTERNAL);
8912  result = query(index, info);
8913  }
8914  if (!result.IsEmpty()) {
8915  ASSERT(result->IsInt32());
8916  return true; // absence of property is signaled by empty handle.
8917  }
8918  } else if (!interceptor->getter()->IsUndefined()) {
8919  v8::IndexedPropertyGetter getter =
8920  v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
8921  LOG(isolate,
8922  ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index));
8923  v8::Handle<v8::Value> result;
8924  {
8925  // Leaving JavaScript.
8926  VMState state(isolate, EXTERNAL);
8927  result = getter(index, info);
8928  }
8929  if (!result.IsEmpty()) return true;
8930  }
8931 
8932  if (holder_handle->GetElementsAccessor()->HasElement(
8933  *receiver_handle, *holder_handle, index)) {
8934  return true;
8935  }
8936 
8937  if (holder_handle->IsStringObjectWithCharacterAt(index)) return true;
8938  Object* pt = holder_handle->GetPrototype();
8939  if (pt->IsJSProxy()) {
8940  // We need to follow the spec and simulate a call to [[GetOwnProperty]].
8942  receiver, index) != ABSENT;
8943  }
8944  if (pt->IsNull()) return false;
8945  return JSObject::cast(pt)->HasElementWithReceiver(*receiver_handle, index);
8946 }
8947 
8948 
8950  // Check access rights if needed.
8951  if (IsAccessCheckNeeded()) {
8952  Heap* heap = GetHeap();
8953  if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
8955  return UNDEFINED_ELEMENT;
8956  }
8957  }
8958 
8959  if (IsJSGlobalProxy()) {
8960  Object* proto = GetPrototype();
8961  if (proto->IsNull()) return UNDEFINED_ELEMENT;
8962  ASSERT(proto->IsJSGlobalObject());
8963  return JSObject::cast(proto)->HasLocalElement(index);
8964  }
8965 
8966  // Check for lookup interceptor
8967  if (HasIndexedInterceptor()) {
8968  return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT
8970  }
8971 
8972  // Handle [] on String objects.
8973  if (this->IsStringObjectWithCharacterAt(index)) {
8974  return STRING_CHARACTER_ELEMENT;
8975  }
8976 
8977  switch (GetElementsKind()) {
8978  case FAST_SMI_ELEMENTS:
8979  case FAST_ELEMENTS:
8981  case FAST_HOLEY_ELEMENTS: {
8982  uint32_t length = IsJSArray() ?
8983  static_cast<uint32_t>
8984  (Smi::cast(JSArray::cast(this)->length())->value()) :
8985  static_cast<uint32_t>(FixedArray::cast(elements())->length());
8986  if ((index < length) &&
8987  !FixedArray::cast(elements())->get(index)->IsTheHole()) {
8988  return FAST_ELEMENT;
8989  }
8990  break;
8991  }
8992  case FAST_DOUBLE_ELEMENTS:
8994  uint32_t length = IsJSArray() ?
8995  static_cast<uint32_t>
8996  (Smi::cast(JSArray::cast(this)->length())->value()) :
8997  static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
8998  if ((index < length) &&
8999  !FixedDoubleArray::cast(elements())->is_the_hole(index)) {
9000  return FAST_ELEMENT;
9001  }
9002  break;
9003  }
9004  case EXTERNAL_PIXEL_ELEMENTS: {
9005  ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9006  if (index < static_cast<uint32_t>(pixels->length())) return FAST_ELEMENT;
9007  break;
9008  }
9013  case EXTERNAL_INT_ELEMENTS:
9016  case EXTERNAL_DOUBLE_ELEMENTS: {
9017  ExternalArray* array = ExternalArray::cast(elements());
9018  if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT;
9019  break;
9020  }
9021  case DICTIONARY_ELEMENTS: {
9022  if (element_dictionary()->FindEntry(index) !=
9024  return DICTIONARY_ELEMENT;
9025  }
9026  break;
9027  }
9029  // Aliased parameters and non-aliased elements in a fast backing store
9030  // behave as FAST_ELEMENT. Non-aliased elements in a dictionary
9031  // backing store behave as DICTIONARY_ELEMENT.
9032  FixedArray* parameter_map = FixedArray::cast(elements());
9033  uint32_t length = parameter_map->length();
9034  Object* probe =
9035  index < (length - 2) ? parameter_map->get(index + 2) : NULL;
9036  if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
9037  // If not aliased, check the arguments.
9038  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
9039  if (arguments->IsDictionary()) {
9040  SeededNumberDictionary* dictionary =
9041  SeededNumberDictionary::cast(arguments);
9042  if (dictionary->FindEntry(index) != SeededNumberDictionary::kNotFound) {
9043  return DICTIONARY_ELEMENT;
9044  }
9045  } else {
9046  length = arguments->length();
9047  probe = (index < length) ? arguments->get(index) : NULL;
9048  if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
9049  }
9050  break;
9051  }
9052  }
9053 
9054  return UNDEFINED_ELEMENT;
9055 }
9056 
9057 
9058 bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
9059  // Check access rights if needed.
9060  if (IsAccessCheckNeeded()) {
9061  Heap* heap = GetHeap();
9062  if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
9064  return false;
9065  }
9066  }
9067 
9068  // Check for lookup interceptor
9069  if (HasIndexedInterceptor()) {
9070  return HasElementWithInterceptor(receiver, index);
9071  }
9072 
9073  ElementsAccessor* accessor = GetElementsAccessor();
9074  if (accessor->HasElement(receiver, this, index)) {
9075  return true;
9076  }
9077 
9078  // Handle [] on String objects.
9079  if (this->IsStringObjectWithCharacterAt(index)) return true;
9080 
9081  Object* pt = GetPrototype();
9082  if (pt->IsNull()) return false;
9083  if (pt->IsJSProxy()) {
9084  // We need to follow the spec and simulate a call to [[GetOwnProperty]].
9086  receiver, index) != ABSENT;
9087  }
9088  return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
9089 }
9090 
9091 
9092 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
9093  Object* value,
9094  PropertyAttributes attributes,
9095  StrictModeFlag strict_mode,
9096  bool check_prototype,
9097  SetPropertyMode set_mode) {
9098  Isolate* isolate = GetIsolate();
9099  // Make sure that the top context does not change when doing
9100  // callbacks or interceptor calls.
9101  AssertNoContextChange ncc;
9102  HandleScope scope(isolate);
9104  Handle<JSObject> this_handle(this);
9105  Handle<Object> value_handle(value, isolate);
9106  if (!interceptor->setter()->IsUndefined()) {
9107  v8::IndexedPropertySetter setter =
9108  v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
9109  LOG(isolate,
9110  ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
9111  CustomArguments args(isolate, interceptor->data(), this, this);
9112  v8::AccessorInfo info(args.end());
9113  v8::Handle<v8::Value> result;
9114  {
9115  // Leaving JavaScript.
9116  VMState state(isolate, EXTERNAL);
9117  result = setter(index, v8::Utils::ToLocal(value_handle), info);
9118  }
9120  if (!result.IsEmpty()) return *value_handle;
9121  }
9122  MaybeObject* raw_result =
9123  this_handle->SetElementWithoutInterceptor(index,
9124  *value_handle,
9125  attributes,
9126  strict_mode,
9127  check_prototype,
9128  set_mode);
9130  return raw_result;
9131 }
9132 
9133 
9134 MaybeObject* JSObject::GetElementWithCallback(Object* receiver,
9135  Object* structure,
9136  uint32_t index,
9137  Object* holder) {
9138  Isolate* isolate = GetIsolate();
9139  ASSERT(!structure->IsForeign());
9140 
9141  // api style callbacks.
9142  if (structure->IsAccessorInfo()) {
9143  Handle<AccessorInfo> data(AccessorInfo::cast(structure));
9144  Object* fun_obj = data->getter();
9145  v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
9146  HandleScope scope(isolate);
9147  Handle<JSObject> self(JSObject::cast(receiver));
9148  Handle<JSObject> holder_handle(JSObject::cast(holder));
9149  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9150  Handle<String> key = isolate->factory()->NumberToString(number);
9151  LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
9152  CustomArguments args(isolate, data->data(), *self, *holder_handle);
9153  v8::AccessorInfo info(args.end());
9154  v8::Handle<v8::Value> result;
9155  {
9156  // Leaving JavaScript.
9157  VMState state(isolate, EXTERNAL);
9158  result = call_fun(v8::Utils::ToLocal(key), info);
9159  }
9161  if (result.IsEmpty()) return isolate->heap()->undefined_value();
9162  return *v8::Utils::OpenHandle(*result);
9163  }
9164 
9165  // __defineGetter__ callback
9166  if (structure->IsAccessorPair()) {
9167  Object* getter = AccessorPair::cast(structure)->getter();
9168  if (getter->IsSpecFunction()) {
9169  // TODO(rossberg): nicer would be to cast to some JSCallable here...
9170  return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
9171  }
9172  // Getter is not a function.
9173  return isolate->heap()->undefined_value();
9174  }
9175 
9176  UNREACHABLE();
9177  return NULL;
9178 }
9179 
9180 
9181 MaybeObject* JSObject::SetElementWithCallback(Object* structure,
9182  uint32_t index,
9183  Object* value,
9184  JSObject* holder,
9185  StrictModeFlag strict_mode) {
9186  Isolate* isolate = GetIsolate();
9187  HandleScope scope(isolate);
9188 
9189  // We should never get here to initialize a const with the hole
9190  // value since a const declaration would conflict with the setter.
9191  ASSERT(!value->IsTheHole());
9192  Handle<Object> value_handle(value, isolate);
9193 
9194  // To accommodate both the old and the new api we switch on the
9195  // data structure used to store the callbacks. Eventually foreign
9196  // callbacks should be phased out.
9197  ASSERT(!structure->IsForeign());
9198 
9199  if (structure->IsAccessorInfo()) {
9200  // api style callbacks
9201  Handle<JSObject> self(this);
9202  Handle<JSObject> holder_handle(JSObject::cast(holder));
9203  Handle<AccessorInfo> data(AccessorInfo::cast(structure));
9204  Object* call_obj = data->setter();
9205  v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
9206  if (call_fun == NULL) return value;
9207  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9208  Handle<String> key(isolate->factory()->NumberToString(number));
9209  LOG(isolate, ApiNamedPropertyAccess("store", *self, *key));
9210  CustomArguments args(isolate, data->data(), *self, *holder_handle);
9211  v8::AccessorInfo info(args.end());
9212  {
9213  // Leaving JavaScript.
9214  VMState state(isolate, EXTERNAL);
9215  call_fun(v8::Utils::ToLocal(key),
9216  v8::Utils::ToLocal(value_handle),
9217  info);
9218  }
9220  return *value_handle;
9221  }
9222 
9223  if (structure->IsAccessorPair()) {
9224  Handle<Object> setter(AccessorPair::cast(structure)->setter());
9225  if (setter->IsSpecFunction()) {
9226  // TODO(rossberg): nicer would be to cast to some JSCallable here...
9227  return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value);
9228  } else {
9229  if (strict_mode == kNonStrictMode) {
9230  return value;
9231  }
9232  Handle<Object> holder_handle(holder, isolate);
9233  Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
9234  Handle<Object> args[2] = { key, holder_handle };
9235  return isolate->Throw(
9236  *isolate->factory()->NewTypeError("no_setter_in_callback",
9237  HandleVector(args, 2)));
9238  }
9239  }
9240 
9241  UNREACHABLE();
9242  return NULL;
9243 }
9244 
9245 
9247  Heap* heap = GetHeap();
9248  if (!elements()->IsFixedArray()) return false;
9249  FixedArray* elements = FixedArray::cast(this->elements());
9250  if (elements->map() != heap->non_strict_arguments_elements_map()) {
9251  return false;
9252  }
9253  FixedArray* arguments = FixedArray::cast(elements->get(1));
9254  return !arguments->IsDictionary();
9255 }
9256 
9257 
9259  Heap* heap = GetHeap();
9260  if (!elements()->IsFixedArray()) return false;
9261  FixedArray* elements = FixedArray::cast(this->elements());
9262  if (elements->map() != heap->non_strict_arguments_elements_map()) {
9263  return false;
9264  }
9265  FixedArray* arguments = FixedArray::cast(elements->get(1));
9266  return arguments->IsDictionary();
9267 }
9268 
9269 
9270 // Adding n elements in fast case is O(n*n).
9271 // Note: revisit design to have dual undefined values to capture absent
9272 // elements.
9273 MaybeObject* JSObject::SetFastElement(uint32_t index,
9274  Object* value,
9275  StrictModeFlag strict_mode,
9276  bool check_prototype) {
9279 
9280  FixedArray* backing_store = FixedArray::cast(elements());
9281  if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
9282  backing_store = FixedArray::cast(backing_store->get(1));
9283  } else {
9284  MaybeObject* maybe = EnsureWritableFastElements();
9285  if (!maybe->To(&backing_store)) return maybe;
9286  }
9287  uint32_t capacity = static_cast<uint32_t>(backing_store->length());
9288 
9289  if (check_prototype &&
9290  (index >= capacity || backing_store->get(index)->IsTheHole())) {
9291  bool found;
9292  MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9293  value,
9294  &found,
9295  strict_mode);
9296  if (found) return result;
9297  }
9298 
9299  uint32_t new_capacity = capacity;
9300  // Check if the length property of this object needs to be updated.
9301  uint32_t array_length = 0;
9302  bool must_update_array_length = false;
9303  bool introduces_holes = true;
9304  if (IsJSArray()) {
9305  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9306  introduces_holes = index > array_length;
9307  if (index >= array_length) {
9308  must_update_array_length = true;
9309  array_length = index + 1;
9310  }
9311  } else {
9312  introduces_holes = index >= capacity;
9313  }
9314 
9315  // If the array is growing, and it's not growth by a single element at the
9316  // end, make sure that the ElementsKind is HOLEY.
9317  ElementsKind elements_kind = GetElementsKind();
9318  if (introduces_holes &&
9319  IsFastElementsKind(elements_kind) &&
9320  !IsFastHoleyElementsKind(elements_kind)) {
9321  ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
9322  MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
9323  if (maybe->IsFailure()) return maybe;
9324  }
9325 
9326  // Check if the capacity of the backing store needs to be increased, or if
9327  // a transition to slow elements is necessary.
9328  if (index >= capacity) {
9329  bool convert_to_slow = true;
9330  if ((index - capacity) < kMaxGap) {
9331  new_capacity = NewElementsCapacity(index + 1);
9332  ASSERT(new_capacity > index);
9333  if (!ShouldConvertToSlowElements(new_capacity)) {
9334  convert_to_slow = false;
9335  }
9336  }
9337  if (convert_to_slow) {
9338  MaybeObject* result = NormalizeElements();
9339  if (result->IsFailure()) return result;
9340  return SetDictionaryElement(index, value, NONE, strict_mode,
9341  check_prototype);
9342  }
9343  }
9344  // Convert to fast double elements if appropriate.
9345  if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
9346  MaybeObject* maybe =
9347  SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
9348  if (maybe->IsFailure()) return maybe;
9349  FixedDoubleArray::cast(elements())->set(index, value->Number());
9350  ValidateElements();
9351  return value;
9352  }
9353  // Change elements kind from Smi-only to generic FAST if necessary.
9354  if (HasFastSmiElements() && !value->IsSmi()) {
9355  Map* new_map;
9358  : FAST_ELEMENTS;
9359  MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
9360  kind);
9361  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9362 
9363  set_map(new_map);
9364  }
9365  // Increase backing store capacity if that's been decided previously.
9366  if (new_capacity != capacity) {
9367  FixedArray* new_elements;
9369  value->IsSmi() && HasFastSmiElements()
9372  { MaybeObject* maybe =
9373  SetFastElementsCapacityAndLength(new_capacity,
9374  array_length,
9375  smi_mode);
9376  if (!maybe->To(&new_elements)) return maybe;
9377  }
9378  new_elements->set(index, value);
9379  ValidateElements();
9380  return value;
9381  }
9382 
9383  // Finally, set the new element and length.
9384  ASSERT(elements()->IsFixedArray());
9385  backing_store->set(index, value);
9386  if (must_update_array_length) {
9387  JSArray::cast(this)->set_length(Smi::FromInt(array_length));
9388  }
9389  return value;
9390 }
9391 
9392 
9393 MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
9394  Object* value,
9395  PropertyAttributes attributes,
9396  StrictModeFlag strict_mode,
9397  bool check_prototype,
9398  SetPropertyMode set_mode) {
9400  Isolate* isolate = GetIsolate();
9401  Heap* heap = isolate->heap();
9402 
9403  // Insert element in the dictionary.
9404  FixedArray* elements = FixedArray::cast(this->elements());
9405  bool is_arguments =
9406  (elements->map() == heap->non_strict_arguments_elements_map());
9407  SeededNumberDictionary* dictionary = NULL;
9408  if (is_arguments) {
9409  dictionary = SeededNumberDictionary::cast(elements->get(1));
9410  } else {
9411  dictionary = SeededNumberDictionary::cast(elements);
9412  }
9413 
9414  int entry = dictionary->FindEntry(index);
9415  if (entry != SeededNumberDictionary::kNotFound) {
9416  Object* element = dictionary->ValueAt(entry);
9417  PropertyDetails details = dictionary->DetailsAt(entry);
9418  if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
9419  return SetElementWithCallback(element, index, value, this, strict_mode);
9420  } else {
9421  dictionary->UpdateMaxNumberKey(index);
9422  // If a value has not been initialized we allow writing to it even if it
9423  // is read-only (a declared const that has not been initialized). If a
9424  // value is being defined we skip attribute checks completely.
9425  if (set_mode == DEFINE_PROPERTY) {
9426  details = PropertyDetails(attributes, NORMAL, details.index());
9427  dictionary->DetailsAtPut(entry, details);
9428  } else if (details.IsReadOnly() && !element->IsTheHole()) {
9429  if (strict_mode == kNonStrictMode) {
9430  return isolate->heap()->undefined_value();
9431  } else {
9432  Handle<Object> holder(this);
9433  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9434  Handle<Object> args[2] = { number, holder };
9435  Handle<Object> error =
9436  isolate->factory()->NewTypeError("strict_read_only_property",
9437  HandleVector(args, 2));
9438  return isolate->Throw(*error);
9439  }
9440  }
9441  // Elements of the arguments object in slow mode might be slow aliases.
9442  if (is_arguments && element->IsAliasedArgumentsEntry()) {
9444  Context* context = Context::cast(elements->get(0));
9445  int context_index = entry->aliased_context_slot();
9446  ASSERT(!context->get(context_index)->IsTheHole());
9447  context->set(context_index, value);
9448  // For elements that are still writable we keep slow aliasing.
9449  if (!details.IsReadOnly()) value = element;
9450  }
9451  dictionary->ValueAtPut(entry, value);
9452  }
9453  } else {
9454  // Index not already used. Look for an accessor in the prototype chain.
9455  if (check_prototype) {
9456  bool found;
9457  MaybeObject* result =
9459  index, value, &found, strict_mode);
9460  if (found) return result;
9461  }
9462  // When we set the is_extensible flag to false we always force the
9463  // element into dictionary mode (and force them to stay there).
9464  if (!map()->is_extensible()) {
9465  if (strict_mode == kNonStrictMode) {
9466  return isolate->heap()->undefined_value();
9467  } else {
9468  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9469  Handle<String> name = isolate->factory()->NumberToString(number);
9470  Handle<Object> args[1] = { name };
9471  Handle<Object> error =
9472  isolate->factory()->NewTypeError("object_not_extensible",
9473  HandleVector(args, 1));
9474  return isolate->Throw(*error);
9475  }
9476  }
9477  FixedArrayBase* new_dictionary;
9478  PropertyDetails details = PropertyDetails(attributes, NORMAL);
9479  MaybeObject* maybe = dictionary->AddNumberEntry(index, value, details);
9480  if (!maybe->To(&new_dictionary)) return maybe;
9481  if (dictionary != SeededNumberDictionary::cast(new_dictionary)) {
9482  if (is_arguments) {
9483  elements->set(1, new_dictionary);
9484  } else {
9485  set_elements(new_dictionary);
9486  }
9487  dictionary = SeededNumberDictionary::cast(new_dictionary);
9488  }
9489  }
9490 
9491  // Update the array length if this JSObject is an array.
9492  if (IsJSArray()) {
9493  MaybeObject* result =
9494  JSArray::cast(this)->JSArrayUpdateLengthFromIndex(index, value);
9495  if (result->IsFailure()) return result;
9496  }
9497 
9498  // Attempt to put this object back in fast case.
9500  uint32_t new_length = 0;
9501  if (IsJSArray()) {
9502  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
9503  } else {
9504  new_length = dictionary->max_number_key() + 1;
9505  }
9506  SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays
9509  bool has_smi_only_elements = false;
9510  bool should_convert_to_fast_double_elements =
9511  ShouldConvertToFastDoubleElements(&has_smi_only_elements);
9512  if (has_smi_only_elements) {
9513  smi_mode = kForceSmiElements;
9514  }
9515  MaybeObject* result = should_convert_to_fast_double_elements
9516  ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
9517  : SetFastElementsCapacityAndLength(new_length,
9518  new_length,
9519  smi_mode);
9520  ValidateElements();
9521  if (result->IsFailure()) return result;
9522 #ifdef DEBUG
9523  if (FLAG_trace_normalization) {
9524  PrintF("Object elements are fast case again:\n");
9525  Print();
9526  }
9527 #endif
9528  }
9529  return value;
9530 }
9531 
9532 
9534  uint32_t index,
9535  Object* value,
9536  StrictModeFlag strict_mode,
9537  bool check_prototype) {
9539 
9540  FixedArrayBase* base_elms = FixedArrayBase::cast(elements());
9541  uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
9542 
9543  // If storing to an element that isn't in the array, pass the store request
9544  // up the prototype chain before storing in the receiver's elements.
9545  if (check_prototype &&
9546  (index >= elms_length ||
9547  FixedDoubleArray::cast(base_elms)->is_the_hole(index))) {
9548  bool found;
9549  MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9550  value,
9551  &found,
9552  strict_mode);
9553  if (found) return result;
9554  }
9555 
9556  // If the value object is not a heap number, switch to fast elements and try
9557  // again.
9558  bool value_is_smi = value->IsSmi();
9559  bool introduces_holes = true;
9560  uint32_t length = elms_length;
9561  if (IsJSArray()) {
9562  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9563  introduces_holes = index > length;
9564  } else {
9565  introduces_holes = index >= elms_length;
9566  }
9567 
9568  if (!value->IsNumber()) {
9569  MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
9570  elms_length,
9571  length,
9573  if (maybe_obj->IsFailure()) return maybe_obj;
9574  maybe_obj = SetFastElement(index, value, strict_mode, check_prototype);
9575  if (maybe_obj->IsFailure()) return maybe_obj;
9576  ValidateElements();
9577  return maybe_obj;
9578  }
9579 
9580  double double_value = value_is_smi
9581  ? static_cast<double>(Smi::cast(value)->value())
9582  : HeapNumber::cast(value)->value();
9583 
9584  // If the array is growing, and it's not growth by a single element at the
9585  // end, make sure that the ElementsKind is HOLEY.
9586  ElementsKind elements_kind = GetElementsKind();
9587  if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
9588  ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
9589  MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
9590  if (maybe->IsFailure()) return maybe;
9591  }
9592 
9593  // Check whether there is extra space in the fixed array.
9594  if (index < elms_length) {
9595  FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9596  elms->set(index, double_value);
9597  if (IsJSArray()) {
9598  // Update the length of the array if needed.
9599  uint32_t array_length = 0;
9600  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9601  if (index >= array_length) {
9602  JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
9603  }
9604  }
9605  return value;
9606  }
9607 
9608  // Allow gap in fast case.
9609  if ((index - elms_length) < kMaxGap) {
9610  // Try allocating extra space.
9611  int new_capacity = NewElementsCapacity(index+1);
9612  if (!ShouldConvertToSlowElements(new_capacity)) {
9613  ASSERT(static_cast<uint32_t>(new_capacity) > index);
9614  MaybeObject* maybe_obj =
9615  SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1);
9616  if (maybe_obj->IsFailure()) return maybe_obj;
9617  FixedDoubleArray::cast(elements())->set(index, double_value);
9618  ValidateElements();
9619  return value;
9620  }
9621  }
9622 
9623  // Otherwise default to slow case.
9625  ASSERT(map()->has_fast_double_elements());
9626  ASSERT(elements()->IsFixedDoubleArray());
9627  Object* obj;
9628  { MaybeObject* maybe_obj = NormalizeElements();
9629  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9630  }
9632  return SetElement(index, value, NONE, strict_mode, check_prototype);
9633 }
9634 
9635 
9636 MaybeObject* JSReceiver::SetElement(uint32_t index,
9637  Object* value,
9638  PropertyAttributes attributes,
9639  StrictModeFlag strict_mode,
9640  bool check_proto) {
9641  if (IsJSProxy()) {
9642  return JSProxy::cast(this)->SetElementWithHandler(
9643  this, index, value, strict_mode);
9644  } else {
9645  return JSObject::cast(this)->SetElement(
9646  index, value, attributes, strict_mode, check_proto);
9647  }
9648 }
9649 
9650 
9652  uint32_t index,
9653  Handle<Object> value,
9654  StrictModeFlag strict_mode) {
9655  ASSERT(!object->HasExternalArrayElements());
9657  object->GetIsolate(),
9658  object->SetElement(index, *value, NONE, strict_mode, false),
9659  Object);
9660 }
9661 
9662 
9664  uint32_t index,
9665  Handle<Object> value,
9666  PropertyAttributes attr,
9667  StrictModeFlag strict_mode,
9668  SetPropertyMode set_mode) {
9669  if (object->HasExternalArrayElements()) {
9670  if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
9671  bool has_exception;
9672  Handle<Object> number = Execution::ToNumber(value, &has_exception);
9673  if (has_exception) return Handle<Object>();
9674  value = number;
9675  }
9676  }
9678  object->GetIsolate(),
9679  object->SetElement(index, *value, attr, strict_mode, true, set_mode),
9680  Object);
9681 }
9682 
9683 
9684 MaybeObject* JSObject::SetElement(uint32_t index,
9685  Object* value,
9686  PropertyAttributes attributes,
9687  StrictModeFlag strict_mode,
9688  bool check_prototype,
9689  SetPropertyMode set_mode) {
9690  // Check access rights if needed.
9691  if (IsAccessCheckNeeded()) {
9692  Heap* heap = GetHeap();
9693  if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
9694  HandleScope scope(heap->isolate());
9695  Handle<Object> value_handle(value);
9697  return *value_handle;
9698  }
9699  }
9700 
9701  if (IsJSGlobalProxy()) {
9702  Object* proto = GetPrototype();
9703  if (proto->IsNull()) return value;
9704  ASSERT(proto->IsJSGlobalObject());
9705  return JSObject::cast(proto)->SetElement(index,
9706  value,
9707  attributes,
9708  strict_mode,
9709  check_prototype,
9710  set_mode);
9711  }
9712 
9713  // Don't allow element properties to be redefined for external arrays.
9714  if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) {
9715  Isolate* isolate = GetHeap()->isolate();
9716  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9717  Handle<Object> args[] = { Handle<Object>(this), number };
9718  Handle<Object> error = isolate->factory()->NewTypeError(
9719  "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args)));
9720  return isolate->Throw(*error);
9721  }
9722 
9723  // Normalize the elements to enable attributes on the property.
9724  if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
9725  SeededNumberDictionary* dictionary;
9726  MaybeObject* maybe_object = NormalizeElements();
9727  if (!maybe_object->To(&dictionary)) return maybe_object;
9728  // Make sure that we never go back to fast case.
9729  dictionary->set_requires_slow_elements();
9730  }
9731 
9732  // Check for lookup interceptor
9733  if (HasIndexedInterceptor()) {
9734  return SetElementWithInterceptor(index,
9735  value,
9736  attributes,
9737  strict_mode,
9738  check_prototype,
9739  set_mode);
9740  }
9741 
9742  return SetElementWithoutInterceptor(index,
9743  value,
9744  attributes,
9745  strict_mode,
9746  check_prototype,
9747  set_mode);
9748 }
9749 
9750 
9751 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
9752  Object* value,
9753  PropertyAttributes attr,
9754  StrictModeFlag strict_mode,
9755  bool check_prototype,
9756  SetPropertyMode set_mode) {
9759  (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
9760  Isolate* isolate = GetIsolate();
9761  switch (GetElementsKind()) {
9762  case FAST_SMI_ELEMENTS:
9763  case FAST_ELEMENTS:
9765  case FAST_HOLEY_ELEMENTS:
9766  return SetFastElement(index, value, strict_mode, check_prototype);
9767  case FAST_DOUBLE_ELEMENTS:
9769  return SetFastDoubleElement(index, value, strict_mode, check_prototype);
9770  case EXTERNAL_PIXEL_ELEMENTS: {
9771  ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9772  return pixels->SetValue(index, value);
9773  }
9774  case EXTERNAL_BYTE_ELEMENTS: {
9775  ExternalByteArray* array = ExternalByteArray::cast(elements());
9776  return array->SetValue(index, value);
9777  }
9779  ExternalUnsignedByteArray* array =
9780  ExternalUnsignedByteArray::cast(elements());
9781  return array->SetValue(index, value);
9782  }
9783  case EXTERNAL_SHORT_ELEMENTS: {
9784  ExternalShortArray* array = ExternalShortArray::cast(elements());
9785  return array->SetValue(index, value);
9786  }
9790  return array->SetValue(index, value);
9791  }
9792  case EXTERNAL_INT_ELEMENTS: {
9793  ExternalIntArray* array = ExternalIntArray::cast(elements());
9794  return array->SetValue(index, value);
9795  }
9797  ExternalUnsignedIntArray* array =
9798  ExternalUnsignedIntArray::cast(elements());
9799  return array->SetValue(index, value);
9800  }
9801  case EXTERNAL_FLOAT_ELEMENTS: {
9802  ExternalFloatArray* array = ExternalFloatArray::cast(elements());
9803  return array->SetValue(index, value);
9804  }
9805  case EXTERNAL_DOUBLE_ELEMENTS: {
9806  ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
9807  return array->SetValue(index, value);
9808  }
9809  case DICTIONARY_ELEMENTS:
9810  return SetDictionaryElement(index, value, attr, strict_mode,
9811  check_prototype, set_mode);
9813  FixedArray* parameter_map = FixedArray::cast(elements());
9814  uint32_t length = parameter_map->length();
9815  Object* probe =
9816  (index < length - 2) ? parameter_map->get(index + 2) : NULL;
9817  if (probe != NULL && !probe->IsTheHole()) {
9818  Context* context = Context::cast(parameter_map->get(0));
9819  int context_index = Smi::cast(probe)->value();
9820  ASSERT(!context->get(context_index)->IsTheHole());
9821  context->set(context_index, value);
9822  // Redefining attributes of an aliased element destroys fast aliasing.
9823  if (set_mode == SET_PROPERTY || attr == NONE) return value;
9824  parameter_map->set_the_hole(index + 2);
9825  // For elements that are still writable we re-establish slow aliasing.
9826  if ((attr & READ_ONLY) == 0) {
9827  MaybeObject* maybe_entry =
9828  isolate->heap()->AllocateAliasedArgumentsEntry(context_index);
9829  if (!maybe_entry->ToObject(&value)) return maybe_entry;
9830  }
9831  }
9832  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
9833  if (arguments->IsDictionary()) {
9834  return SetDictionaryElement(index, value, attr, strict_mode,
9835  check_prototype, set_mode);
9836  } else {
9837  return SetFastElement(index, value, strict_mode, check_prototype);
9838  }
9839  }
9840  }
9841  // All possible cases have been handled above. Add a return to avoid the
9842  // complaints from the compiler.
9843  UNREACHABLE();
9844  return isolate->heap()->null_value();
9845 }
9846 
9847 
9849  ElementsKind to_kind) {
9850  CALL_HEAP_FUNCTION(object->GetIsolate(),
9851  object->TransitionElementsKind(to_kind),
9852  Object);
9853 }
9854 
9855 
9857  ElementsKind from_kind = map()->elements_kind();
9858 
9859  if (IsFastHoleyElementsKind(from_kind)) {
9860  to_kind = GetHoleyElementsKind(to_kind);
9861  }
9862 
9863  Isolate* isolate = GetIsolate();
9864  if (elements() == isolate->heap()->empty_fixed_array() ||
9865  (IsFastSmiOrObjectElementsKind(from_kind) &&
9866  IsFastSmiOrObjectElementsKind(to_kind)) ||
9867  (from_kind == FAST_DOUBLE_ELEMENTS &&
9868  to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
9869  ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
9870  // No change is needed to the elements() buffer, the transition
9871  // only requires a map change.
9872  MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
9873  Map* new_map;
9874  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9875  set_map(new_map);
9876  if (FLAG_trace_elements_transitions) {
9877  FixedArrayBase* elms = FixedArrayBase::cast(elements());
9878  PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
9879  }
9880  return this;
9881  }
9882 
9883  FixedArrayBase* elms = FixedArrayBase::cast(elements());
9884  uint32_t capacity = static_cast<uint32_t>(elms->length());
9885  uint32_t length = capacity;
9886 
9887  if (IsJSArray()) {
9888  Object* raw_length = JSArray::cast(this)->length();
9889  if (raw_length->IsUndefined()) {
9890  // If length is undefined, then JSArray is being initialized and has no
9891  // elements, assume a length of zero.
9892  length = 0;
9893  } else {
9894  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9895  }
9896  }
9897 
9898  if (IsFastSmiElementsKind(from_kind) &&
9899  IsFastDoubleElementsKind(to_kind)) {
9900  MaybeObject* maybe_result =
9901  SetFastDoubleElementsCapacityAndLength(capacity, length);
9902  if (maybe_result->IsFailure()) return maybe_result;
9903  ValidateElements();
9904  return this;
9905  }
9906 
9907  if (IsFastDoubleElementsKind(from_kind) &&
9908  IsFastObjectElementsKind(to_kind)) {
9909  MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
9910  capacity, length, kDontAllowSmiElements);
9911  if (maybe_result->IsFailure()) return maybe_result;
9912  ValidateElements();
9913  return this;
9914  }
9915 
9916  // This method should never be called for any other case than the ones
9917  // handled above.
9918  UNREACHABLE();
9919  return GetIsolate()->heap()->null_value();
9920 }
9921 
9922 
9923 // static
9925  ElementsKind to_kind) {
9926  // Transitions can't go backwards.
9927  if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
9928  return false;
9929  }
9930 
9931  // Transitions from HOLEY -> PACKED are not allowed.
9932  return !IsFastHoleyElementsKind(from_kind) ||
9933  IsFastHoleyElementsKind(to_kind);
9934 }
9935 
9936 
9937 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
9938  Object* value) {
9939  uint32_t old_len = 0;
9940  CHECK(length()->ToArrayIndex(&old_len));
9941  // Check to see if we need to update the length. For now, we make
9942  // sure that the length stays within 32-bits (unsigned).
9943  if (index >= old_len && index != 0xffffffff) {
9944  Object* len;
9945  { MaybeObject* maybe_len =
9946  GetHeap()->NumberFromDouble(static_cast<double>(index) + 1);
9947  if (!maybe_len->ToObject(&len)) return maybe_len;
9948  }
9949  set_length(len);
9950  }
9951  return value;
9952 }
9953 
9954 
9956  uint32_t index) {
9957  Isolate* isolate = GetIsolate();
9958  // Make sure that the top context does not change when doing
9959  // callbacks or interceptor calls.
9960  AssertNoContextChange ncc;
9961  HandleScope scope(isolate);
9962  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate);
9963  Handle<Object> this_handle(receiver, isolate);
9964  Handle<JSObject> holder_handle(this, isolate);
9965  if (!interceptor->getter()->IsUndefined()) {
9966  v8::IndexedPropertyGetter getter =
9967  v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
9968  LOG(isolate,
9969  ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
9970  CustomArguments args(isolate, interceptor->data(), receiver, this);
9971  v8::AccessorInfo info(args.end());
9972  v8::Handle<v8::Value> result;
9973  {
9974  // Leaving JavaScript.
9975  VMState state(isolate, EXTERNAL);
9976  result = getter(index, info);
9977  }
9979  if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
9980  }
9981 
9982  Heap* heap = holder_handle->GetHeap();
9983  ElementsAccessor* handler = holder_handle->GetElementsAccessor();
9984  MaybeObject* raw_result = handler->Get(*this_handle,
9985  *holder_handle,
9986  index);
9987  if (raw_result != heap->the_hole_value()) return raw_result;
9988 
9990 
9991  Object* pt = holder_handle->GetPrototype();
9992  if (pt == heap->null_value()) return heap->undefined_value();
9993  return pt->GetElementWithReceiver(*this_handle, index);
9994 }
9995 
9996 
9997 bool JSObject::HasDenseElements() {
9998  int capacity = 0;
9999  int used = 0;
10000  GetElementsCapacityAndUsage(&capacity, &used);
10001  return (capacity == 0) || (used > (capacity / 2));
10002 }
10003 
10004 
10005 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
10006  *capacity = 0;
10007  *used = 0;
10008 
10009  FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
10010  FixedArray* backing_store = NULL;
10011  switch (GetElementsKind()) {
10013  backing_store_base =
10014  FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
10015  backing_store = FixedArray::cast(backing_store_base);
10016  if (backing_store->IsDictionary()) {
10017  SeededNumberDictionary* dictionary =
10018  SeededNumberDictionary::cast(backing_store);
10019  *capacity = dictionary->Capacity();
10020  *used = dictionary->NumberOfElements();
10021  break;
10022  }
10023  // Fall through.
10024  case FAST_SMI_ELEMENTS:
10025  case FAST_ELEMENTS:
10026  if (IsJSArray()) {
10027  *capacity = backing_store_base->length();
10028  *used = Smi::cast(JSArray::cast(this)->length())->value();
10029  break;
10030  }
10031  // Fall through if packing is not guaranteed.
10033  case FAST_HOLEY_ELEMENTS:
10034  backing_store = FixedArray::cast(backing_store_base);
10035  *capacity = backing_store->length();
10036  for (int i = 0; i < *capacity; ++i) {
10037  if (!backing_store->get(i)->IsTheHole()) ++(*used);
10038  }
10039  break;
10040  case DICTIONARY_ELEMENTS: {
10041  SeededNumberDictionary* dictionary =
10043  *capacity = dictionary->Capacity();
10044  *used = dictionary->NumberOfElements();
10045  break;
10046  }
10047  case FAST_DOUBLE_ELEMENTS:
10048  if (IsJSArray()) {
10049  *capacity = backing_store_base->length();
10050  *used = Smi::cast(JSArray::cast(this)->length())->value();
10051  break;
10052  }
10053  // Fall through if packing is not guaranteed.
10055  FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
10056  *capacity = elms->length();
10057  for (int i = 0; i < *capacity; i++) {
10058  if (!elms->is_the_hole(i)) ++(*used);
10059  }
10060  break;
10061  }
10066  case EXTERNAL_INT_ELEMENTS:
10071  // External arrays are considered 100% used.
10072  ExternalArray* external_array = ExternalArray::cast(elements());
10073  *capacity = external_array->length();
10074  *used = external_array->length();
10075  break;
10076  }
10077 }
10078 
10079 
10083  if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
10084  (new_capacity <= kMaxUncheckedFastElementsLength &&
10085  GetHeap()->InNewSpace(this))) {
10086  return false;
10087  }
10088  // If the fast-case backing storage takes up roughly three times as
10089  // much space (in machine words) as a dictionary backing storage
10090  // would, the object should have slow elements.
10091  int old_capacity = 0;
10092  int used_elements = 0;
10093  GetElementsCapacityAndUsage(&old_capacity, &used_elements);
10094  int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
10096  return 3 * dictionary_size <= new_capacity;
10097 }
10098 
10099 
10102  // If the elements are sparse, we should not go back to fast case.
10103  if (!HasDenseElements()) return false;
10104  // An object requiring access checks is never allowed to have fast
10105  // elements. If it had fast elements we would skip security checks.
10106  if (IsAccessCheckNeeded()) return false;
10107 
10108  FixedArray* elements = FixedArray::cast(this->elements());
10109  SeededNumberDictionary* dictionary = NULL;
10110  if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
10111  dictionary = SeededNumberDictionary::cast(elements->get(1));
10112  } else {
10113  dictionary = SeededNumberDictionary::cast(elements);
10114  }
10115  // If an element has been added at a very high index in the elements
10116  // dictionary, we cannot go back to fast case.
10117  if (dictionary->requires_slow_elements()) return false;
10118  // If the dictionary backing storage takes up roughly half as much
10119  // space (in machine words) as a fast-case backing storage would,
10120  // the object should have fast elements.
10121  uint32_t array_size = 0;
10122  if (IsJSArray()) {
10123  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
10124  } else {
10125  array_size = dictionary->max_number_key();
10126  }
10127  uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
10129  return 2 * dictionary_size >= array_size;
10130 }
10131 
10132 
10134  bool* has_smi_only_elements) {
10135  *has_smi_only_elements = false;
10136  if (FLAG_unbox_double_arrays) {
10138  SeededNumberDictionary* dictionary =
10139  SeededNumberDictionary::cast(elements());
10140  bool found_double = false;
10141  for (int i = 0; i < dictionary->Capacity(); i++) {
10142  Object* key = dictionary->KeyAt(i);
10143  if (key->IsNumber()) {
10144  Object* value = dictionary->ValueAt(i);
10145  if (!value->IsNumber()) return false;
10146  if (!value->IsSmi()) {
10147  found_double = true;
10148  }
10149  }
10150  }
10151  *has_smi_only_elements = !found_double;
10152  return found_double;
10153  } else {
10154  return false;
10155  }
10156 }
10157 
10158 
10159 // Certain compilers request function template instantiation when they
10160 // see the definition of the other template functions in the
10161 // class. This requires us to have the template functions put
10162 // together, so even though this function belongs in objects-debug.cc,
10163 // we keep it here instead to satisfy certain compilers.
10164 #ifdef OBJECT_PRINT
10165 template<typename Shape, typename Key>
10166 void Dictionary<Shape, Key>::Print(FILE* out) {
10167  int capacity = HashTable<Shape, Key>::Capacity();
10168  for (int i = 0; i < capacity; i++) {
10171  PrintF(out, " ");
10172  if (k->IsString()) {
10173  String::cast(k)->StringPrint(out);
10174  } else {
10175  k->ShortPrint(out);
10176  }
10177  PrintF(out, ": ");
10178  ValueAt(i)->ShortPrint(out);
10179  PrintF(out, "\n");
10180  }
10181  }
10182 }
10183 #endif
10184 
10185 
10186 template<typename Shape, typename Key>
10188  int pos = 0;
10189  int capacity = HashTable<Shape, Key>::Capacity();
10190  AssertNoAllocation no_gc;
10191  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
10192  for (int i = 0; i < capacity; i++) {
10195  elements->set(pos++, ValueAt(i), mode);
10196  }
10197  }
10198  ASSERT(pos == elements->length());
10199 }
10200 
10201 
10203  ASSERT(map()->has_named_interceptor());
10204  JSFunction* constructor = JSFunction::cast(map()->constructor());
10205  ASSERT(constructor->shared()->IsApiFunction());
10206  Object* result =
10207  constructor->shared()->get_api_func_data()->named_property_handler();
10208  return InterceptorInfo::cast(result);
10209 }
10210 
10211 
10213  ASSERT(map()->has_indexed_interceptor());
10214  JSFunction* constructor = JSFunction::cast(map()->constructor());
10215  ASSERT(constructor->shared()->IsApiFunction());
10216  Object* result =
10217  constructor->shared()->get_api_func_data()->indexed_property_handler();
10218  return InterceptorInfo::cast(result);
10219 }
10220 
10221 
10223  JSReceiver* receiver,
10224  String* name,
10225  PropertyAttributes* attributes) {
10226  // Check local property in holder, ignore interceptor.
10227  LookupResult result(GetIsolate());
10228  LocalLookupRealNamedProperty(name, &result);
10229  if (result.IsProperty()) {
10230  return GetProperty(receiver, &result, name, attributes);
10231  }
10232  // Continue searching via the prototype chain.
10233  Object* pt = GetPrototype();
10234  *attributes = ABSENT;
10235  if (pt->IsNull()) return GetHeap()->undefined_value();
10236  return pt->GetPropertyWithReceiver(receiver, name, attributes);
10237 }
10238 
10239 
10241  JSReceiver* receiver,
10242  String* name,
10243  PropertyAttributes* attributes) {
10244  // Check local property in holder, ignore interceptor.
10245  LookupResult result(GetIsolate());
10246  LocalLookupRealNamedProperty(name, &result);
10247  if (result.IsProperty()) {
10248  return GetProperty(receiver, &result, name, attributes);
10249  }
10250  return GetHeap()->undefined_value();
10251 }
10252 
10253 
10255  JSReceiver* receiver,
10256  String* name,
10257  PropertyAttributes* attributes) {
10258  Isolate* isolate = GetIsolate();
10259  InterceptorInfo* interceptor = GetNamedInterceptor();
10260  HandleScope scope(isolate);
10261  Handle<JSReceiver> receiver_handle(receiver);
10262  Handle<JSObject> holder_handle(this);
10263  Handle<String> name_handle(name);
10264 
10265  if (!interceptor->getter()->IsUndefined()) {
10266  v8::NamedPropertyGetter getter =
10267  v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
10268  LOG(isolate,
10269  ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
10270  CustomArguments args(isolate, interceptor->data(), receiver, this);
10271  v8::AccessorInfo info(args.end());
10272  v8::Handle<v8::Value> result;
10273  {
10274  // Leaving JavaScript.
10275  VMState state(isolate, EXTERNAL);
10276  result = getter(v8::Utils::ToLocal(name_handle), info);
10277  }
10279  if (!result.IsEmpty()) {
10280  *attributes = NONE;
10281  return *v8::Utils::OpenHandle(*result);
10282  }
10283  }
10284 
10285  MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
10286  *receiver_handle,
10287  *name_handle,
10288  attributes);
10290  return result;
10291 }
10292 
10293 
10295  // Check access rights if needed.
10296  Isolate* isolate = GetIsolate();
10297  if (IsAccessCheckNeeded()) {
10298  if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
10299  isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10300  return false;
10301  }
10302  }
10303 
10304  LookupResult result(isolate);
10305  LocalLookupRealNamedProperty(key, &result);
10306  return result.IsProperty() && (result.type() != INTERCEPTOR);
10307 }
10308 
10309 
10310 bool JSObject::HasRealElementProperty(uint32_t index) {
10311  // Check access rights if needed.
10312  if (IsAccessCheckNeeded()) {
10313  Heap* heap = GetHeap();
10314  if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
10316  return false;
10317  }
10318  }
10319 
10320  // Handle [] on String objects.
10321  if (this->IsStringObjectWithCharacterAt(index)) return true;
10322 
10323  switch (GetElementsKind()) {
10324  case FAST_SMI_ELEMENTS:
10325  case FAST_ELEMENTS:
10327  case FAST_HOLEY_ELEMENTS: {
10328  uint32_t length = IsJSArray() ?
10329  static_cast<uint32_t>(
10330  Smi::cast(JSArray::cast(this)->length())->value()) :
10331  static_cast<uint32_t>(FixedArray::cast(elements())->length());
10332  return (index < length) &&
10333  !FixedArray::cast(elements())->get(index)->IsTheHole();
10334  }
10335  case FAST_DOUBLE_ELEMENTS:
10337  uint32_t length = IsJSArray() ?
10338  static_cast<uint32_t>(
10339  Smi::cast(JSArray::cast(this)->length())->value()) :
10340  static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
10341  return (index < length) &&
10342  !FixedDoubleArray::cast(elements())->is_the_hole(index);
10343  break;
10344  }
10345  case EXTERNAL_PIXEL_ELEMENTS: {
10346  ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
10347  return index < static_cast<uint32_t>(pixels->length());
10348  }
10353  case EXTERNAL_INT_ELEMENTS:
10356  case EXTERNAL_DOUBLE_ELEMENTS: {
10357  ExternalArray* array = ExternalArray::cast(elements());
10358  return index < static_cast<uint32_t>(array->length());
10359  }
10360  case DICTIONARY_ELEMENTS: {
10361  return element_dictionary()->FindEntry(index)
10363  }
10365  UNIMPLEMENTED();
10366  break;
10367  }
10368  // All possibilities have been handled above already.
10369  UNREACHABLE();
10370  return GetHeap()->null_value();
10371 }
10372 
10373 
10375  // Check access rights if needed.
10376  Isolate* isolate = GetIsolate();
10377  if (IsAccessCheckNeeded()) {
10378  if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
10379  isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10380  return false;
10381  }
10382  }
10383 
10384  LookupResult result(isolate);
10385  LocalLookupRealNamedProperty(key, &result);
10386  return result.IsFound() && (result.type() == CALLBACKS);
10387 }
10388 
10389 
10391  return HasFastProperties() ?
10392  map()->NumberOfDescribedProperties(filter) :
10394 }
10395 
10396 
10397 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
10398  Object* temp = get(i);
10399  set(i, get(j));
10400  set(j, temp);
10401  if (this != numbers) {
10402  temp = numbers->get(i);
10403  numbers->set(i, Smi::cast(numbers->get(j)));
10404  numbers->set(j, Smi::cast(temp));
10405  }
10406 }
10407 
10408 
10409 static void InsertionSortPairs(FixedArray* content,
10410  FixedArray* numbers,
10411  int len) {
10412  for (int i = 1; i < len; i++) {
10413  int j = i;
10414  while (j > 0 &&
10415  (NumberToUint32(numbers->get(j - 1)) >
10416  NumberToUint32(numbers->get(j)))) {
10417  content->SwapPairs(numbers, j - 1, j);
10418  j--;
10419  }
10420  }
10421 }
10422 
10423 
10424 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
10425  // In-place heap sort.
10426  ASSERT(content->length() == numbers->length());
10427 
10428  // Bottom-up max-heap construction.
10429  for (int i = 1; i < len; ++i) {
10430  int child_index = i;
10431  while (child_index > 0) {
10432  int parent_index = ((child_index + 1) >> 1) - 1;
10433  uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
10434  uint32_t child_value = NumberToUint32(numbers->get(child_index));
10435  if (parent_value < child_value) {
10436  content->SwapPairs(numbers, parent_index, child_index);
10437  } else {
10438  break;
10439  }
10440  child_index = parent_index;
10441  }
10442  }
10443 
10444  // Extract elements and create sorted array.
10445  for (int i = len - 1; i > 0; --i) {
10446  // Put max element at the back of the array.
10447  content->SwapPairs(numbers, 0, i);
10448  // Sift down the new top element.
10449  int parent_index = 0;
10450  while (true) {
10451  int child_index = ((parent_index + 1) << 1) - 1;
10452  if (child_index >= i) break;
10453  uint32_t child1_value = NumberToUint32(numbers->get(child_index));
10454  uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
10455  uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
10456  if (child_index + 1 >= i || child1_value > child2_value) {
10457  if (parent_value > child1_value) break;
10458  content->SwapPairs(numbers, parent_index, child_index);
10459  parent_index = child_index;
10460  } else {
10461  if (parent_value > child2_value) break;
10462  content->SwapPairs(numbers, parent_index, child_index + 1);
10463  parent_index = child_index + 1;
10464  }
10465  }
10466  }
10467 }
10468 
10469 
10470 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
10471 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
10472  ASSERT(this->length() == numbers->length());
10473  // For small arrays, simply use insertion sort.
10474  if (len <= 10) {
10475  InsertionSortPairs(this, numbers, len);
10476  return;
10477  }
10478  // Check the range of indices.
10479  uint32_t min_index = NumberToUint32(numbers->get(0));
10480  uint32_t max_index = min_index;
10481  uint32_t i;
10482  for (i = 1; i < len; i++) {
10483  if (NumberToUint32(numbers->get(i)) < min_index) {
10484  min_index = NumberToUint32(numbers->get(i));
10485  } else if (NumberToUint32(numbers->get(i)) > max_index) {
10486  max_index = NumberToUint32(numbers->get(i));
10487  }
10488  }
10489  if (max_index - min_index + 1 == len) {
10490  // Indices form a contiguous range, unless there are duplicates.
10491  // Do an in-place linear time sort assuming distinct numbers, but
10492  // avoid hanging in case they are not.
10493  for (i = 0; i < len; i++) {
10494  uint32_t p;
10495  uint32_t j = 0;
10496  // While the current element at i is not at its correct position p,
10497  // swap the elements at these two positions.
10498  while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
10499  j++ < len) {
10500  SwapPairs(numbers, i, p);
10501  }
10502  }
10503  } else {
10504  HeapSortPairs(this, numbers, len);
10505  return;
10506  }
10507 }
10508 
10509 
10510 // Fill in the names of local properties into the supplied storage. The main
10511 // purpose of this function is to provide reflection information for the object
10512 // mirrors.
10513 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
10514  ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
10515  if (HasFastProperties()) {
10516  DescriptorArray* descs = map()->instance_descriptors();
10517  for (int i = 0; i < descs->number_of_descriptors(); i++) {
10518  if (descs->IsProperty(i)) storage->set(index++, descs->GetKey(i));
10519  }
10520  ASSERT(storage->length() >= index);
10521  } else {
10522  property_dictionary()->CopyKeysTo(storage,
10523  index,
10525  }
10526 }
10527 
10528 
10530  return GetLocalElementKeys(NULL, filter);
10531 }
10532 
10533 
10535  // Fast case for objects with no elements.
10536  if (!IsJSValue() && HasFastObjectElements()) {
10537  uint32_t length = IsJSArray() ?
10538  static_cast<uint32_t>(
10539  Smi::cast(JSArray::cast(this)->length())->value()) :
10540  static_cast<uint32_t>(FixedArray::cast(elements())->length());
10541  if (length == 0) return 0;
10542  }
10543  // Compute the number of enumerable elements.
10544  return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
10545 }
10546 
10547 
10549  PropertyAttributes filter) {
10550  int counter = 0;
10551  switch (GetElementsKind()) {
10552  case FAST_SMI_ELEMENTS:
10553  case FAST_ELEMENTS:
10555  case FAST_HOLEY_ELEMENTS: {
10556  int length = IsJSArray() ?
10557  Smi::cast(JSArray::cast(this)->length())->value() :
10558  FixedArray::cast(elements())->length();
10559  for (int i = 0; i < length; i++) {
10560  if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
10561  if (storage != NULL) {
10562  storage->set(counter, Smi::FromInt(i));
10563  }
10564  counter++;
10565  }
10566  }
10567  ASSERT(!storage || storage->length() >= counter);
10568  break;
10569  }
10570  case FAST_DOUBLE_ELEMENTS:
10572  int length = IsJSArray() ?
10573  Smi::cast(JSArray::cast(this)->length())->value() :
10574  FixedDoubleArray::cast(elements())->length();
10575  for (int i = 0; i < length; i++) {
10576  if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
10577  if (storage != NULL) {
10578  storage->set(counter, Smi::FromInt(i));
10579  }
10580  counter++;
10581  }
10582  }
10583  ASSERT(!storage || storage->length() >= counter);
10584  break;
10585  }
10586  case EXTERNAL_PIXEL_ELEMENTS: {
10587  int length = ExternalPixelArray::cast(elements())->length();
10588  while (counter < length) {
10589  if (storage != NULL) {
10590  storage->set(counter, Smi::FromInt(counter));
10591  }
10592  counter++;
10593  }
10594  ASSERT(!storage || storage->length() >= counter);
10595  break;
10596  }
10601  case EXTERNAL_INT_ELEMENTS:
10604  case EXTERNAL_DOUBLE_ELEMENTS: {
10605  int length = ExternalArray::cast(elements())->length();
10606  while (counter < length) {
10607  if (storage != NULL) {
10608  storage->set(counter, Smi::FromInt(counter));
10609  }
10610  counter++;
10611  }
10612  ASSERT(!storage || storage->length() >= counter);
10613  break;
10614  }
10615  case DICTIONARY_ELEMENTS: {
10616  if (storage != NULL) {
10617  element_dictionary()->CopyKeysTo(storage,
10618  filter,
10620  }
10622  break;
10623  }
10625  FixedArray* parameter_map = FixedArray::cast(elements());
10626  int mapped_length = parameter_map->length() - 2;
10627  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
10628  if (arguments->IsDictionary()) {
10629  // Copy the keys from arguments first, because Dictionary::CopyKeysTo
10630  // will insert in storage starting at index 0.
10631  SeededNumberDictionary* dictionary =
10632  SeededNumberDictionary::cast(arguments);
10633  if (storage != NULL) {
10634  dictionary->CopyKeysTo(
10635  storage, filter, SeededNumberDictionary::UNSORTED);
10636  }
10637  counter += dictionary->NumberOfElementsFilterAttributes(filter);
10638  for (int i = 0; i < mapped_length; ++i) {
10639  if (!parameter_map->get(i + 2)->IsTheHole()) {
10640  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10641  ++counter;
10642  }
10643  }
10644  if (storage != NULL) storage->SortPairs(storage, counter);
10645 
10646  } else {
10647  int backing_length = arguments->length();
10648  int i = 0;
10649  for (; i < mapped_length; ++i) {
10650  if (!parameter_map->get(i + 2)->IsTheHole()) {
10651  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10652  ++counter;
10653  } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
10654  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10655  ++counter;
10656  }
10657  }
10658  for (; i < backing_length; ++i) {
10659  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10660  ++counter;
10661  }
10662  }
10663  break;
10664  }
10665  }
10666 
10667  if (this->IsJSValue()) {
10668  Object* val = JSValue::cast(this)->value();
10669  if (val->IsString()) {
10670  String* str = String::cast(val);
10671  if (storage) {
10672  for (int i = 0; i < str->length(); i++) {
10673  storage->set(counter + i, Smi::FromInt(i));
10674  }
10675  }
10676  counter += str->length();
10677  }
10678  }
10679  ASSERT(!storage || storage->length() == counter);
10680  return counter;
10681 }
10682 
10683 
10685  return GetLocalElementKeys(storage,
10686  static_cast<PropertyAttributes>(DONT_ENUM));
10687 }
10688 
10689 
10690 // StringKey simply carries a string object as key.
10691 class StringKey : public HashTableKey {
10692  public:
10693  explicit StringKey(String* string) :
10694  string_(string),
10695  hash_(HashForObject(string)) { }
10696 
10697  bool IsMatch(Object* string) {
10698  // We know that all entries in a hash table had their hash keys created.
10699  // Use that knowledge to have fast failure.
10700  if (hash_ != HashForObject(string)) {
10701  return false;
10702  }
10703  return string_->Equals(String::cast(string));
10704  }
10705 
10706  uint32_t Hash() { return hash_; }
10707 
10708  uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
10709 
10710  Object* AsObject() { return string_; }
10711 
10713  uint32_t hash_;
10714 };
10715 
10716 
10717 // StringSharedKeys are used as keys in the eval cache.
10719  public:
10721  SharedFunctionInfo* shared,
10722  LanguageMode language_mode,
10723  int scope_position)
10724  : source_(source),
10725  shared_(shared),
10726  language_mode_(language_mode),
10727  scope_position_(scope_position) { }
10728 
10729  bool IsMatch(Object* other) {
10730  if (!other->IsFixedArray()) return false;
10731  FixedArray* other_array = FixedArray::cast(other);
10732  SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
10733  if (shared != shared_) return false;
10734  int language_unchecked = Smi::cast(other_array->get(2))->value();
10735  ASSERT(language_unchecked == CLASSIC_MODE ||
10736  language_unchecked == STRICT_MODE ||
10737  language_unchecked == EXTENDED_MODE);
10738  LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
10739  if (language_mode != language_mode_) return false;
10740  int scope_position = Smi::cast(other_array->get(3))->value();
10741  if (scope_position != scope_position_) return false;
10742  String* source = String::cast(other_array->get(1));
10743  return source->Equals(source_);
10744  }
10745 
10746  static uint32_t StringSharedHashHelper(String* source,
10747  SharedFunctionInfo* shared,
10748  LanguageMode language_mode,
10749  int scope_position) {
10750  uint32_t hash = source->Hash();
10751  if (shared->HasSourceCode()) {
10752  // Instead of using the SharedFunctionInfo pointer in the hash
10753  // code computation, we use a combination of the hash of the
10754  // script source code and the start position of the calling scope.
10755  // We do this to ensure that the cache entries can survive garbage
10756  // collection.
10757  Script* script = Script::cast(shared->script());
10758  hash ^= String::cast(script->source())->Hash();
10759  if (language_mode == STRICT_MODE) hash ^= 0x8000;
10760  if (language_mode == EXTENDED_MODE) hash ^= 0x0080;
10761  hash += scope_position;
10762  }
10763  return hash;
10764  }
10765 
10766  uint32_t Hash() {
10767  return StringSharedHashHelper(
10768  source_, shared_, language_mode_, scope_position_);
10769  }
10770 
10771  uint32_t HashForObject(Object* obj) {
10772  FixedArray* other_array = FixedArray::cast(obj);
10773  SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
10774  String* source = String::cast(other_array->get(1));
10775  int language_unchecked = Smi::cast(other_array->get(2))->value();
10776  ASSERT(language_unchecked == CLASSIC_MODE ||
10777  language_unchecked == STRICT_MODE ||
10778  language_unchecked == EXTENDED_MODE);
10779  LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
10780  int scope_position = Smi::cast(other_array->get(3))->value();
10781  return StringSharedHashHelper(
10782  source, shared, language_mode, scope_position);
10783  }
10784 
10785  MUST_USE_RESULT MaybeObject* AsObject() {
10786  Object* obj;
10787  { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(4);
10788  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10789  }
10790  FixedArray* other_array = FixedArray::cast(obj);
10791  other_array->set(0, shared_);
10792  other_array->set(1, source_);
10793  other_array->set(2, Smi::FromInt(language_mode_));
10794  other_array->set(3, Smi::FromInt(scope_position_));
10795  return other_array;
10796  }
10797 
10798  private:
10799  String* source_;
10800  SharedFunctionInfo* shared_;
10801  LanguageMode language_mode_;
10802  int scope_position_;
10803 };
10804 
10805 
10806 // RegExpKey carries the source and flags of a regular expression as key.
10807 class RegExpKey : public HashTableKey {
10808  public:
10810  : string_(string),
10811  flags_(Smi::FromInt(flags.value())) { }
10812 
10813  // Rather than storing the key in the hash table, a pointer to the
10814  // stored value is stored where the key should be. IsMatch then
10815  // compares the search key to the found object, rather than comparing
10816  // a key to a key.
10817  bool IsMatch(Object* obj) {
10818  FixedArray* val = FixedArray::cast(obj);
10819  return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
10820  && (flags_ == val->get(JSRegExp::kFlagsIndex));
10821  }
10822 
10823  uint32_t Hash() { return RegExpHash(string_, flags_); }
10824 
10826  // Plain hash maps, which is where regexp keys are used, don't
10827  // use this function.
10828  UNREACHABLE();
10829  return NULL;
10830  }
10831 
10832  uint32_t HashForObject(Object* obj) {
10833  FixedArray* val = FixedArray::cast(obj);
10834  return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
10836  }
10837 
10838  static uint32_t RegExpHash(String* string, Smi* flags) {
10839  return string->Hash() + flags->value();
10840  }
10841 
10844 };
10845 
10846 // Utf8SymbolKey carries a vector of chars as key.
10847 class Utf8SymbolKey : public HashTableKey {
10848  public:
10849  explicit Utf8SymbolKey(Vector<const char> string, uint32_t seed)
10850  : string_(string), hash_field_(0), seed_(seed) { }
10851 
10852  bool IsMatch(Object* string) {
10853  return String::cast(string)->IsEqualTo(string_);
10854  }
10855 
10856  uint32_t Hash() {
10857  if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
10858  unibrow::Utf8InputBuffer<> buffer(string_.start(),
10859  static_cast<unsigned>(string_.length()));
10860  chars_ = buffer.Utf16Length();
10861  hash_field_ = String::ComputeHashField(&buffer, chars_, seed_);
10862  uint32_t result = hash_field_ >> String::kHashShift;
10863  ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
10864  return result;
10865  }
10866 
10867  uint32_t HashForObject(Object* other) {
10868  return String::cast(other)->Hash();
10869  }
10870 
10871  MaybeObject* AsObject() {
10872  if (hash_field_ == 0) Hash();
10873  return Isolate::Current()->heap()->AllocateSymbol(
10874  string_, chars_, hash_field_);
10875  }
10876 
10878  uint32_t hash_field_;
10879  int chars_; // Caches the number of characters when computing the hash code.
10880  uint32_t seed_;
10881 };
10882 
10883 
10884 template <typename Char>
10886  public:
10887  explicit SequentialSymbolKey(Vector<const Char> string, uint32_t seed)
10888  : string_(string), hash_field_(0), seed_(seed) { }
10889 
10890  uint32_t Hash() {
10891  StringHasher hasher(string_.length(), seed_);
10892 
10893  // Very long strings have a trivial hash that doesn't inspect the
10894  // string contents.
10895  if (hasher.has_trivial_hash()) {
10896  hash_field_ = hasher.GetHashField();
10897  } else {
10898  int i = 0;
10899  // Do the iterative array index computation as long as there is a
10900  // chance this is an array index.
10901  while (i < string_.length() && hasher.is_array_index()) {
10902  hasher.AddCharacter(static_cast<uc32>(string_[i]));
10903  i++;
10904  }
10905 
10906  // Process the remaining characters without updating the array
10907  // index.
10908  while (i < string_.length()) {
10909  hasher.AddCharacterNoIndex(static_cast<uc32>(string_[i]));
10910  i++;
10911  }
10912  hash_field_ = hasher.GetHashField();
10913  }
10914 
10915  uint32_t result = hash_field_ >> String::kHashShift;
10916  ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
10917  return result;
10918  }
10919 
10920 
10921  uint32_t HashForObject(Object* other) {
10922  return String::cast(other)->Hash();
10923  }
10924 
10926  uint32_t hash_field_;
10927  uint32_t seed_;
10928 };
10929 
10930 
10931 
10932 class AsciiSymbolKey : public SequentialSymbolKey<char> {
10933  public:
10935  : SequentialSymbolKey<char>(str, seed) { }
10936 
10937  bool IsMatch(Object* string) {
10938  return String::cast(string)->IsAsciiEqualTo(string_);
10939  }
10940 
10941  MaybeObject* AsObject() {
10942  if (hash_field_ == 0) Hash();
10943  return HEAP->AllocateAsciiSymbol(string_, hash_field_);
10944  }
10945 };
10946 
10947 
10949  public:
10951  int from,
10952  int length,
10953  uint32_t seed)
10954  : string_(string), from_(from), length_(length), seed_(seed) { }
10955 
10956  uint32_t Hash() {
10957  ASSERT(length_ >= 0);
10958  ASSERT(from_ + length_ <= string_->length());
10959  StringHasher hasher(length_, string_->GetHeap()->HashSeed());
10960 
10961  // Very long strings have a trivial hash that doesn't inspect the
10962  // string contents.
10963  if (hasher.has_trivial_hash()) {
10964  hash_field_ = hasher.GetHashField();
10965  } else {
10966  int i = 0;
10967  // Do the iterative array index computation as long as there is a
10968  // chance this is an array index.
10969  while (i < length_ && hasher.is_array_index()) {
10970  hasher.AddCharacter(static_cast<uc32>(
10971  string_->SeqAsciiStringGet(i + from_)));
10972  i++;
10973  }
10974 
10975  // Process the remaining characters without updating the array
10976  // index.
10977  while (i < length_) {
10978  hasher.AddCharacterNoIndex(static_cast<uc32>(
10979  string_->SeqAsciiStringGet(i + from_)));
10980  i++;
10981  }
10982  hash_field_ = hasher.GetHashField();
10983  }
10984 
10985  uint32_t result = hash_field_ >> String::kHashShift;
10986  ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
10987  return result;
10988  }
10989 
10990 
10991  uint32_t HashForObject(Object* other) {
10992  return String::cast(other)->Hash();
10993  }
10994 
10995  bool IsMatch(Object* string) {
10996  Vector<const char> chars(string_->GetChars() + from_, length_);
10997  return String::cast(string)->IsAsciiEqualTo(chars);
10998  }
10999 
11000  MaybeObject* AsObject() {
11001  if (hash_field_ == 0) Hash();
11002  Vector<const char> chars(string_->GetChars() + from_, length_);
11003  return HEAP->AllocateAsciiSymbol(chars, hash_field_);
11004  }
11005 
11006  private:
11007  Handle<SeqAsciiString> string_;
11008  int from_;
11009  int length_;
11010  uint32_t hash_field_;
11011  uint32_t seed_;
11012 };
11013 
11014 
11016  public:
11017  explicit TwoByteSymbolKey(Vector<const uc16> str, uint32_t seed)
11018  : SequentialSymbolKey<uc16>(str, seed) { }
11019 
11020  bool IsMatch(Object* string) {
11021  return String::cast(string)->IsTwoByteEqualTo(string_);
11022  }
11023 
11024  MaybeObject* AsObject() {
11025  if (hash_field_ == 0) Hash();
11026  return HEAP->AllocateTwoByteSymbol(string_, hash_field_);
11027  }
11028 };
11029 
11030 
11031 // SymbolKey carries a string/symbol object as key.
11032 class SymbolKey : public HashTableKey {
11033  public:
11034  explicit SymbolKey(String* string)
11035  : string_(string) { }
11036 
11037  bool IsMatch(Object* string) {
11038  return String::cast(string)->Equals(string_);
11039  }
11040 
11041  uint32_t Hash() { return string_->Hash(); }
11042 
11043  uint32_t HashForObject(Object* other) {
11044  return String::cast(other)->Hash();
11045  }
11046 
11047  MaybeObject* AsObject() {
11048  // Attempt to flatten the string, so that symbols will most often
11049  // be flat strings.
11050  string_ = string_->TryFlattenGetString();
11051  Heap* heap = string_->GetHeap();
11052  // Transform string to symbol if possible.
11053  Map* map = heap->SymbolMapForString(string_);
11054  if (map != NULL) {
11055  string_->set_map_no_write_barrier(map);
11056  ASSERT(string_->IsSymbol());
11057  return string_;
11058  }
11059  // Otherwise allocate a new symbol.
11060  StringInputBuffer buffer(string_);
11061  return heap->AllocateInternalSymbol(&buffer,
11062  string_->length(),
11063  string_->hash_field());
11064  }
11065 
11066  static uint32_t StringHash(Object* obj) {
11067  return String::cast(obj)->Hash();
11068  }
11069 
11071 };
11072 
11073 
11074 template<typename Shape, typename Key>
11076  IteratePointers(v, 0, kElementsStartOffset);
11077 }
11078 
11079 
11080 template<typename Shape, typename Key>
11082  IteratePointers(v,
11083  kElementsStartOffset,
11084  kHeaderSize + length() * kPointerSize);
11085 }
11086 
11087 
11088 template<typename Shape, typename Key>
11089 MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for,
11090  PretenureFlag pretenure) {
11091  int capacity = ComputeCapacity(at_least_space_for);
11092  if (capacity > HashTable::kMaxCapacity) {
11094  }
11095 
11096  Object* obj;
11097  { MaybeObject* maybe_obj = Isolate::Current()->heap()->
11098  AllocateHashTable(EntryToIndex(capacity), pretenure);
11099  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11100  }
11103  HashTable::cast(obj)->SetCapacity(capacity);
11104  return obj;
11105 }
11106 
11107 
11108 // Find entry for key otherwise return kNotFound.
11110  if (!key->IsSymbol()) {
11112  }
11113 
11114  // Optimized for symbol key. Knowledge of the key type allows:
11115  // 1. Move the check if the key is a symbol out of the loop.
11116  // 2. Avoid comparing hash codes in symbol to symbol comparison.
11117  // 3. Detect a case when a dictionary key is not a symbol but the key is.
11118  // In case of positive result the dictionary key may be replaced by
11119  // the symbol with minimal performance penalty. It gives a chance to
11120  // perform further lookups in code stubs (and significant performance boost
11121  // a certain style of code).
11122 
11123  // EnsureCapacity will guarantee the hash table is never full.
11124  uint32_t capacity = Capacity();
11125  uint32_t entry = FirstProbe(key->Hash(), capacity);
11126  uint32_t count = 1;
11127 
11128  while (true) {
11129  int index = EntryToIndex(entry);
11130  Object* element = get(index);
11131  if (element->IsUndefined()) break; // Empty entry.
11132  if (key == element) return entry;
11133  if (!element->IsSymbol() &&
11134  !element->IsTheHole() &&
11135  String::cast(element)->Equals(key)) {
11136  // Replace a non-symbol key by the equivalent symbol for faster further
11137  // lookups.
11138  set(index, key);
11139  return entry;
11140  }
11141  ASSERT(element->IsTheHole() || !String::cast(element)->Equals(key));
11142  entry = NextProbe(entry, count++, capacity);
11143  }
11144  return kNotFound;
11145 }
11146 
11147 
11149  switch (DetailsAt(entry).type()) {
11150  case MAP_TRANSITION:
11151  case CONSTANT_TRANSITION:
11152  return true;
11153  case CALLBACKS: {
11154  Object* value = ValueAt(entry);
11155  if (!value->IsAccessorPair()) return false;
11156  AccessorPair* accessors = AccessorPair::cast(value);
11157  return accessors->getter()->IsMap() || accessors->setter()->IsMap();
11158  }
11159  case NORMAL:
11160  case FIELD:
11161  case CONSTANT_FUNCTION:
11162  case HANDLER:
11163  case INTERCEPTOR:
11164  case NULL_DESCRIPTOR:
11165  return false;
11166  }
11167  UNREACHABLE(); // Keep the compiler happy.
11168  return false;
11169 }
11170 
11171 
11172 template<typename Shape, typename Key>
11173 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) {
11174  ASSERT(NumberOfElements() < new_table->Capacity());
11175 
11176  AssertNoAllocation no_gc;
11177  WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
11178 
11179  // Copy prefix to new array.
11180  for (int i = kPrefixStartIndex;
11181  i < kPrefixStartIndex + Shape::kPrefixSize;
11182  i++) {
11183  new_table->set(i, get(i), mode);
11184  }
11185 
11186  // Rehash the elements.
11187  int capacity = Capacity();
11188  for (int i = 0; i < capacity; i++) {
11189  uint32_t from_index = EntryToIndex(i);
11190  Object* k = get(from_index);
11191  if (IsKey(k)) {
11192  uint32_t hash = HashTable<Shape, Key>::HashForObject(key, k);
11193  uint32_t insertion_index =
11194  EntryToIndex(new_table->FindInsertionEntry(hash));
11195  for (int j = 0; j < Shape::kEntrySize; j++) {
11196  new_table->set(insertion_index + j, get(from_index + j), mode);
11197  }
11198  }
11199  }
11200  new_table->SetNumberOfElements(NumberOfElements());
11201  new_table->SetNumberOfDeletedElements(0);
11202  return new_table;
11203 }
11204 
11205 
11206 template<typename Shape, typename Key>
11207 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
11208  int capacity = Capacity();
11209  int nof = NumberOfElements() + n;
11210  int nod = NumberOfDeletedElements();
11211  // Return if:
11212  // 50% is still free after adding n elements and
11213  // at most 50% of the free elements are deleted elements.
11214  if (nod <= (capacity - nof) >> 1) {
11215  int needed_free = nof >> 1;
11216  if (nof + needed_free <= capacity) return this;
11217  }
11218 
11219  const int kMinCapacityForPretenure = 256;
11220  bool pretenure =
11221  (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this);
11222  Object* obj;
11223  { MaybeObject* maybe_obj =
11224  Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED);
11225  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11226  }
11227 
11228  return Rehash(HashTable::cast(obj), key);
11229 }
11230 
11231 
11232 template<typename Shape, typename Key>
11233 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) {
11234  int capacity = Capacity();
11235  int nof = NumberOfElements();
11236 
11237  // Shrink to fit the number of elements if only a quarter of the
11238  // capacity is filled with elements.
11239  if (nof > (capacity >> 2)) return this;
11240  // Allocate a new dictionary with room for at least the current
11241  // number of elements. The allocation method will make sure that
11242  // there is extra room in the dictionary for additions. Don't go
11243  // lower than room for 16 elements.
11244  int at_least_room_for = nof;
11245  if (at_least_room_for < 16) return this;
11246 
11247  const int kMinCapacityForPretenure = 256;
11248  bool pretenure =
11249  (at_least_room_for > kMinCapacityForPretenure) &&
11250  !GetHeap()->InNewSpace(this);
11251  Object* obj;
11252  { MaybeObject* maybe_obj =
11253  Allocate(at_least_room_for, pretenure ? TENURED : NOT_TENURED);
11254  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11255  }
11256 
11257  return Rehash(HashTable::cast(obj), key);
11258 }
11259 
11260 
11261 template<typename Shape, typename Key>
11263  uint32_t capacity = Capacity();
11264  uint32_t entry = FirstProbe(hash, capacity);
11265  uint32_t count = 1;
11266  // EnsureCapacity will guarantee the hash table is never full.
11267  while (true) {
11268  Object* element = KeyAt(entry);
11269  if (element->IsUndefined() || element->IsTheHole()) break;
11270  entry = NextProbe(entry, count++, capacity);
11271  }
11272  return entry;
11273 }
11274 
11275 // Force instantiation of template instances class.
11276 // Please note this list is compiler dependent.
11277 
11279 
11281 
11283 
11284 template class HashTable<ObjectHashTableShape<1>, Object*>;
11285 
11286 template class HashTable<ObjectHashTableShape<2>, Object*>;
11287 
11289 
11291 
11293 
11295  Allocate(int at_least_space_for);
11296 
11298  Allocate(int at_least_space_for);
11299 
11301  int);
11302 
11304  uint32_t, Object*);
11305 
11307  AtPut(uint32_t, Object*);
11308 
11310  SlowReverseLookup(Object* value);
11311 
11313  SlowReverseLookup(Object* value);
11314 
11316  Object*);
11317 
11319  FixedArray*,
11322 
11324  int, JSObject::DeleteMode);
11325 
11328 
11330  String*);
11331 
11333  uint32_t);
11334 
11336  FixedArray*,
11337  int,
11339 
11340 template int
11343 
11345  String*, Object*, PropertyDetails);
11346 
11347 template MaybeObject*
11349 
11350 template int
11353 
11355  uint32_t, Object*, PropertyDetails);
11356 
11358  uint32_t, Object*, PropertyDetails);
11359 
11361  EnsureCapacity(int, uint32_t);
11362 
11364  EnsureCapacity(int, uint32_t);
11365 
11367  EnsureCapacity(int, String*);
11368 
11370  AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
11371 
11373  AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
11374 
11376  String*, Object*, PropertyDetails, uint32_t);
11377 
11378 template
11380 
11381 template
11383 
11384 template
11386 
11387 
11388 // Collates undefined and unexisting elements below limit from position
11389 // zero of the elements. The object stays in Dictionary mode.
11390 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
11392  // Must stay in dictionary mode, either because of requires_slow_elements,
11393  // or because we are not going to sort (and therefore compact) all of the
11394  // elements.
11396  HeapNumber* result_double = NULL;
11397  if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
11398  // Allocate space for result before we start mutating the object.
11399  Object* new_double;
11400  { MaybeObject* maybe_new_double = GetHeap()->AllocateHeapNumber(0.0);
11401  if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
11402  }
11403  result_double = HeapNumber::cast(new_double);
11404  }
11405 
11406  Object* obj;
11407  { MaybeObject* maybe_obj =
11409  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11410  }
11412 
11413  AssertNoAllocation no_alloc;
11414 
11415  uint32_t pos = 0;
11416  uint32_t undefs = 0;
11417  int capacity = dict->Capacity();
11418  for (int i = 0; i < capacity; i++) {
11419  Object* k = dict->KeyAt(i);
11420  if (dict->IsKey(k)) {
11421  ASSERT(k->IsNumber());
11422  ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
11423  ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
11424  ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
11425  Object* value = dict->ValueAt(i);
11426  PropertyDetails details = dict->DetailsAt(i);
11427  if (details.type() == CALLBACKS) {
11428  // Bail out and do the sorting of undefineds and array holes in JS.
11429  return Smi::FromInt(-1);
11430  }
11431  uint32_t key = NumberToUint32(k);
11432  // In the following we assert that adding the entry to the new dictionary
11433  // does not cause GC. This is the case because we made sure to allocate
11434  // the dictionary big enough above, so it need not grow.
11435  if (key < limit) {
11436  if (value->IsUndefined()) {
11437  undefs++;
11438  } else {
11439  if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
11440  // Adding an entry with the key beyond smi-range requires
11441  // allocation. Bailout.
11442  return Smi::FromInt(-1);
11443  }
11444  new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked();
11445  pos++;
11446  }
11447  } else {
11448  if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
11449  // Adding an entry with the key beyond smi-range requires
11450  // allocation. Bailout.
11451  return Smi::FromInt(-1);
11452  }
11453  new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
11454  }
11455  }
11456  }
11457 
11458  uint32_t result = pos;
11459  PropertyDetails no_details = PropertyDetails(NONE, NORMAL);
11460  Heap* heap = GetHeap();
11461  while (undefs > 0) {
11462  if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
11463  // Adding an entry with the key beyond smi-range requires
11464  // allocation. Bailout.
11465  return Smi::FromInt(-1);
11466  }
11467  new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
11468  ToObjectUnchecked();
11469  pos++;
11470  undefs--;
11471  }
11472 
11473  set_elements(new_dict);
11474 
11475  if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
11476  return Smi::FromInt(static_cast<int>(result));
11477  }
11478 
11479  ASSERT_NE(NULL, result_double);
11480  result_double->set_value(static_cast<double>(result));
11481  return result_double;
11482 }
11483 
11484 
11485 // Collects all defined (non-hole) and non-undefined (array) elements at
11486 // the start of the elements array.
11487 // If the object is in dictionary mode, it is converted to fast elements
11488 // mode.
11489 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
11490  Heap* heap = GetHeap();
11491 
11492  if (HasDictionaryElements()) {
11493  // Convert to fast elements containing only the existing properties.
11494  // Ordering is irrelevant, since we are going to sort anyway.
11496  if (IsJSArray() || dict->requires_slow_elements() ||
11497  dict->max_number_key() >= limit) {
11498  return PrepareSlowElementsForSort(limit);
11499  }
11500  // Convert to fast elements.
11501 
11502  Object* obj;
11503  MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
11505  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11506  Map* new_map = Map::cast(obj);
11507 
11508  PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
11509  Object* new_array;
11510  { MaybeObject* maybe_new_array =
11511  heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
11512  if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
11513  }
11514  FixedArray* fast_elements = FixedArray::cast(new_array);
11515  dict->CopyValuesTo(fast_elements);
11516  ValidateElements();
11517 
11518  set_map_and_elements(new_map, fast_elements);
11519  } else if (HasExternalArrayElements()) {
11520  // External arrays cannot have holes or undefined elements.
11521  return Smi::FromInt(ExternalArray::cast(elements())->length());
11522  } else if (!HasFastDoubleElements()) {
11523  Object* obj;
11524  { MaybeObject* maybe_obj = EnsureWritableFastElements();
11525  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11526  }
11527  }
11529 
11530  // Collect holes at the end, undefined before that and the rest at the
11531  // start, and return the number of non-hole, non-undefined values.
11532 
11533  FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
11534  uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
11535  if (limit > elements_length) {
11536  limit = elements_length ;
11537  }
11538  if (limit == 0) {
11539  return Smi::FromInt(0);
11540  }
11541 
11542  HeapNumber* result_double = NULL;
11543  if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
11544  // Pessimistically allocate space for return value before
11545  // we start mutating the array.
11546  Object* new_double;
11547  { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0);
11548  if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
11549  }
11550  result_double = HeapNumber::cast(new_double);
11551  }
11552 
11553  uint32_t result = 0;
11554  if (elements_base->map() == heap->fixed_double_array_map()) {
11555  FixedDoubleArray* elements = FixedDoubleArray::cast(elements_base);
11556  // Split elements into defined and the_hole, in that order.
11557  unsigned int holes = limit;
11558  // Assume most arrays contain no holes and undefined values, so minimize the
11559  // number of stores of non-undefined, non-the-hole values.
11560  for (unsigned int i = 0; i < holes; i++) {
11561  if (elements->is_the_hole(i)) {
11562  holes--;
11563  } else {
11564  continue;
11565  }
11566  // Position i needs to be filled.
11567  while (holes > i) {
11568  if (elements->is_the_hole(holes)) {
11569  holes--;
11570  } else {
11571  elements->set(i, elements->get_scalar(holes));
11572  break;
11573  }
11574  }
11575  }
11576  result = holes;
11577  while (holes < limit) {
11578  elements->set_the_hole(holes);
11579  holes++;
11580  }
11581  } else {
11582  FixedArray* elements = FixedArray::cast(elements_base);
11583  AssertNoAllocation no_alloc;
11584 
11585  // Split elements into defined, undefined and the_hole, in that order. Only
11586  // count locations for undefined and the hole, and fill them afterwards.
11587  WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc);
11588  unsigned int undefs = limit;
11589  unsigned int holes = limit;
11590  // Assume most arrays contain no holes and undefined values, so minimize the
11591  // number of stores of non-undefined, non-the-hole values.
11592  for (unsigned int i = 0; i < undefs; i++) {
11593  Object* current = elements->get(i);
11594  if (current->IsTheHole()) {
11595  holes--;
11596  undefs--;
11597  } else if (current->IsUndefined()) {
11598  undefs--;
11599  } else {
11600  continue;
11601  }
11602  // Position i needs to be filled.
11603  while (undefs > i) {
11604  current = elements->get(undefs);
11605  if (current->IsTheHole()) {
11606  holes--;
11607  undefs--;
11608  } else if (current->IsUndefined()) {
11609  undefs--;
11610  } else {
11611  elements->set(i, current, write_barrier);
11612  break;
11613  }
11614  }
11615  }
11616  result = undefs;
11617  while (undefs < holes) {
11618  elements->set_undefined(undefs);
11619  undefs++;
11620  }
11621  while (holes < limit) {
11622  elements->set_the_hole(holes);
11623  holes++;
11624  }
11625  }
11626 
11627  if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
11628  return Smi::FromInt(static_cast<int>(result));
11629  }
11630  ASSERT_NE(NULL, result_double);
11631  result_double->set_value(static_cast<double>(result));
11632  return result_double;
11633 }
11634 
11635 
11636 Object* ExternalPixelArray::SetValue(uint32_t index, Object* value) {
11637  uint8_t clamped_value = 0;
11638  if (index < static_cast<uint32_t>(length())) {
11639  if (value->IsSmi()) {
11640  int int_value = Smi::cast(value)->value();
11641  if (int_value < 0) {
11642  clamped_value = 0;
11643  } else if (int_value > 255) {
11644  clamped_value = 255;
11645  } else {
11646  clamped_value = static_cast<uint8_t>(int_value);
11647  }
11648  } else if (value->IsHeapNumber()) {
11649  double double_value = HeapNumber::cast(value)->value();
11650  if (!(double_value > 0)) {
11651  // NaN and less than zero clamp to zero.
11652  clamped_value = 0;
11653  } else if (double_value > 255) {
11654  // Greater than 255 clamp to 255.
11655  clamped_value = 255;
11656  } else {
11657  // Other doubles are rounded to the nearest integer.
11658  clamped_value = static_cast<uint8_t>(double_value + 0.5);
11659  }
11660  } else {
11661  // Clamp undefined to zero (default). All other types have been
11662  // converted to a number type further up in the call chain.
11663  ASSERT(value->IsUndefined());
11664  }
11665  set(index, clamped_value);
11666  }
11667  return Smi::FromInt(clamped_value);
11668 }
11669 
11670 
11671 template<typename ExternalArrayClass, typename ValueType>
11672 static MaybeObject* ExternalArrayIntSetter(Heap* heap,
11673  ExternalArrayClass* receiver,
11674  uint32_t index,
11675  Object* value) {
11676  ValueType cast_value = 0;
11677  if (index < static_cast<uint32_t>(receiver->length())) {
11678  if (value->IsSmi()) {
11679  int int_value = Smi::cast(value)->value();
11680  cast_value = static_cast<ValueType>(int_value);
11681  } else if (value->IsHeapNumber()) {
11682  double double_value = HeapNumber::cast(value)->value();
11683  cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
11684  } else {
11685  // Clamp undefined to zero (default). All other types have been
11686  // converted to a number type further up in the call chain.
11687  ASSERT(value->IsUndefined());
11688  }
11689  receiver->set(index, cast_value);
11690  }
11691  return heap->NumberFromInt32(cast_value);
11692 }
11693 
11694 
11695 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) {
11696  return ExternalArrayIntSetter<ExternalByteArray, int8_t>
11697  (GetHeap(), this, index, value);
11698 }
11699 
11700 
11701 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index,
11702  Object* value) {
11703  return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t>
11704  (GetHeap(), this, index, value);
11705 }
11706 
11707 
11708 MaybeObject* ExternalShortArray::SetValue(uint32_t index,
11709  Object* value) {
11710  return ExternalArrayIntSetter<ExternalShortArray, int16_t>
11711  (GetHeap(), this, index, value);
11712 }
11713 
11714 
11715 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index,
11716  Object* value) {
11717  return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t>
11718  (GetHeap(), this, index, value);
11719 }
11720 
11721 
11722 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) {
11723  return ExternalArrayIntSetter<ExternalIntArray, int32_t>
11724  (GetHeap(), this, index, value);
11725 }
11726 
11727 
11728 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) {
11729  uint32_t cast_value = 0;
11730  Heap* heap = GetHeap();
11731  if (index < static_cast<uint32_t>(length())) {
11732  if (value->IsSmi()) {
11733  int int_value = Smi::cast(value)->value();
11734  cast_value = static_cast<uint32_t>(int_value);
11735  } else if (value->IsHeapNumber()) {
11736  double double_value = HeapNumber::cast(value)->value();
11737  cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
11738  } else {
11739  // Clamp undefined to zero (default). All other types have been
11740  // converted to a number type further up in the call chain.
11741  ASSERT(value->IsUndefined());
11742  }
11743  set(index, cast_value);
11744  }
11745  return heap->NumberFromUint32(cast_value);
11746 }
11747 
11748 
11749 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) {
11750  float cast_value = static_cast<float>(OS::nan_value());
11751  Heap* heap = GetHeap();
11752  if (index < static_cast<uint32_t>(length())) {
11753  if (value->IsSmi()) {
11754  int int_value = Smi::cast(value)->value();
11755  cast_value = static_cast<float>(int_value);
11756  } else if (value->IsHeapNumber()) {
11757  double double_value = HeapNumber::cast(value)->value();
11758  cast_value = static_cast<float>(double_value);
11759  } else {
11760  // Clamp undefined to NaN (default). All other types have been
11761  // converted to a number type further up in the call chain.
11762  ASSERT(value->IsUndefined());
11763  }
11764  set(index, cast_value);
11765  }
11766  return heap->AllocateHeapNumber(cast_value);
11767 }
11768 
11769 
11770 MaybeObject* ExternalDoubleArray::SetValue(uint32_t index, Object* value) {
11771  double double_value = OS::nan_value();
11772  Heap* heap = GetHeap();
11773  if (index < static_cast<uint32_t>(length())) {
11774  if (value->IsSmi()) {
11775  int int_value = Smi::cast(value)->value();
11776  double_value = static_cast<double>(int_value);
11777  } else if (value->IsHeapNumber()) {
11778  double_value = HeapNumber::cast(value)->value();
11779  } else {
11780  // Clamp undefined to NaN (default). All other types have been
11781  // converted to a number type further up in the call chain.
11782  ASSERT(value->IsUndefined());
11783  }
11784  set(index, double_value);
11785  }
11786  return heap->AllocateHeapNumber(double_value);
11787 }
11788 
11789 
11792  Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
11793  return JSGlobalPropertyCell::cast(value);
11794 }
11795 
11796 
11798  Handle<GlobalObject> global,
11799  Handle<String> name) {
11800  Isolate* isolate = global->GetIsolate();
11801  CALL_HEAP_FUNCTION(isolate,
11802  global->EnsurePropertyCell(*name),
11804 }
11805 
11806 
11809  int entry = property_dictionary()->FindEntry(name);
11810  if (entry == StringDictionary::kNotFound) {
11811  Heap* heap = GetHeap();
11812  Object* cell;
11813  { MaybeObject* maybe_cell =
11814  heap->AllocateJSGlobalPropertyCell(heap->the_hole_value());
11815  if (!maybe_cell->ToObject(&cell)) return maybe_cell;
11816  }
11817  PropertyDetails details(NONE, NORMAL);
11818  details = details.AsDeleted();
11819  Object* dictionary;
11820  { MaybeObject* maybe_dictionary =
11821  property_dictionary()->Add(name, cell, details);
11822  if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary;
11823  }
11824  set_properties(StringDictionary::cast(dictionary));
11825  return cell;
11826  } else {
11827  Object* value = property_dictionary()->ValueAt(entry);
11828  ASSERT(value->IsJSGlobalPropertyCell());
11829  return value;
11830  }
11831 }
11832 
11833 
11834 MaybeObject* SymbolTable::LookupString(String* string, Object** s) {
11835  SymbolKey key(string);
11836  return LookupKey(&key, s);
11837 }
11838 
11839 
11840 // This class is used for looking up two character strings in the symbol table.
11841 // If we don't have a hit we don't want to waste much time so we unroll the
11842 // string hash calculation loop here for speed. Doesn't work if the two
11843 // characters form a decimal integer, since such strings have a different hash
11844 // algorithm.
11846  public:
11847  TwoCharHashTableKey(uint32_t c1, uint32_t c2, uint32_t seed)
11848  : c1_(c1), c2_(c2) {
11849  // Char 1.
11850  uint32_t hash = seed;
11851  hash += c1;
11852  hash += hash << 10;
11853  hash ^= hash >> 6;
11854  // Char 2.
11855  hash += c2;
11856  hash += hash << 10;
11857  hash ^= hash >> 6;
11858  // GetHash.
11859  hash += hash << 3;
11860  hash ^= hash >> 11;
11861  hash += hash << 15;
11862  if ((hash & String::kHashBitMask) == 0) hash = String::kZeroHash;
11863 #ifdef DEBUG
11864  StringHasher hasher(2, seed);
11865  hasher.AddCharacter(c1);
11866  hasher.AddCharacter(c2);
11867  // If this assert fails then we failed to reproduce the two-character
11868  // version of the string hashing algorithm above. One reason could be
11869  // that we were passed two digits as characters, since the hash
11870  // algorithm is different in that case.
11871  ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash));
11872 #endif
11873  hash_ = hash;
11874  }
11875 
11876  bool IsMatch(Object* o) {
11877  if (!o->IsString()) return false;
11878  String* other = String::cast(o);
11879  if (other->length() != 2) return false;
11880  if (other->Get(0) != c1_) return false;
11881  return other->Get(1) == c2_;
11882  }
11883 
11884  uint32_t Hash() { return hash_; }
11885  uint32_t HashForObject(Object* key) {
11886  if (!key->IsString()) return 0;
11887  return String::cast(key)->Hash();
11888  }
11889 
11890  Object* AsObject() {
11891  // The TwoCharHashTableKey is only used for looking in the symbol
11892  // table, not for adding to it.
11893  UNREACHABLE();
11894  return NULL;
11895  }
11896 
11897  private:
11898  uint32_t c1_;
11899  uint32_t c2_;
11900  uint32_t hash_;
11901 };
11902 
11903 
11905  SymbolKey key(string);
11906  int entry = FindEntry(&key);
11907  if (entry == kNotFound) {
11908  return false;
11909  } else {
11910  String* result = String::cast(KeyAt(entry));
11911  ASSERT(StringShape(result).IsSymbol());
11912  *symbol = result;
11913  return true;
11914  }
11915 }
11916 
11917 
11919  uint32_t c2,
11920  String** symbol) {
11921  TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed());
11922  int entry = FindEntry(&key);
11923  if (entry == kNotFound) {
11924  return false;
11925  } else {
11926  String* result = String::cast(KeyAt(entry));
11927  ASSERT(StringShape(result).IsSymbol());
11928  *symbol = result;
11929  return true;
11930  }
11931 }
11932 
11933 
11935  Object** s) {
11936  Utf8SymbolKey key(str, GetHeap()->HashSeed());
11937  return LookupKey(&key, s);
11938 }
11939 
11940 
11942  Object** s) {
11943  AsciiSymbolKey key(str, GetHeap()->HashSeed());
11944  return LookupKey(&key, s);
11945 }
11946 
11947 
11949  int from,
11950  int length,
11951  Object** s) {
11952  SubStringAsciiSymbolKey key(str, from, length, GetHeap()->HashSeed());
11953  return LookupKey(&key, s);
11954 }
11955 
11956 
11958  Object** s) {
11959  TwoByteSymbolKey key(str, GetHeap()->HashSeed());
11960  return LookupKey(&key, s);
11961 }
11962 
11963 MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
11964  int entry = FindEntry(key);
11965 
11966  // Symbol already in table.
11967  if (entry != kNotFound) {
11968  *s = KeyAt(entry);
11969  return this;
11970  }
11971 
11972  // Adding new symbol. Grow table if needed.
11973  Object* obj;
11974  { MaybeObject* maybe_obj = EnsureCapacity(1, key);
11975  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11976  }
11977 
11978  // Create symbol object.
11979  Object* symbol;
11980  { MaybeObject* maybe_symbol = key->AsObject();
11981  if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol;
11982  }
11983 
11984  // If the symbol table grew as part of EnsureCapacity, obj is not
11985  // the current symbol table and therefore we cannot use
11986  // SymbolTable::cast here.
11987  SymbolTable* table = reinterpret_cast<SymbolTable*>(obj);
11988 
11989  // Add the new symbol and return it along with the symbol table.
11990  entry = table->FindInsertionEntry(key->Hash());
11991  table->set(EntryToIndex(entry), symbol);
11992  table->ElementAdded();
11993  *s = symbol;
11994  return table;
11995 }
11996 
11997 
11999  StringKey key(src);
12000  int entry = FindEntry(&key);
12001  if (entry == kNotFound) return GetHeap()->undefined_value();
12002  return get(EntryToIndex(entry) + 1);
12003 }
12004 
12005 
12007  Context* context,
12008  LanguageMode language_mode,
12009  int scope_position) {
12010  StringSharedKey key(src,
12011  context->closure()->shared(),
12012  language_mode,
12013  scope_position);
12014  int entry = FindEntry(&key);
12015  if (entry == kNotFound) return GetHeap()->undefined_value();
12016  return get(EntryToIndex(entry) + 1);
12017 }
12018 
12019 
12021  JSRegExp::Flags flags) {
12022  RegExpKey key(src, flags);
12023  int entry = FindEntry(&key);
12024  if (entry == kNotFound) return GetHeap()->undefined_value();
12025  return get(EntryToIndex(entry) + 1);
12026 }
12027 
12028 
12029 MaybeObject* CompilationCacheTable::Put(String* src, Object* value) {
12030  StringKey key(src);
12031  Object* obj;
12032  { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
12033  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12034  }
12035 
12036  CompilationCacheTable* cache =
12037  reinterpret_cast<CompilationCacheTable*>(obj);
12038  int entry = cache->FindInsertionEntry(key.Hash());
12039  cache->set(EntryToIndex(entry), src);
12040  cache->set(EntryToIndex(entry) + 1, value);
12041  cache->ElementAdded();
12042  return cache;
12043 }
12044 
12045 
12047  Context* context,
12048  SharedFunctionInfo* value,
12049  int scope_position) {
12050  StringSharedKey key(src,
12051  context->closure()->shared(),
12052  value->language_mode(),
12053  scope_position);
12054  Object* obj;
12055  { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
12056  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12057  }
12058 
12059  CompilationCacheTable* cache =
12060  reinterpret_cast<CompilationCacheTable*>(obj);
12061  int entry = cache->FindInsertionEntry(key.Hash());
12062 
12063  Object* k;
12064  { MaybeObject* maybe_k = key.AsObject();
12065  if (!maybe_k->ToObject(&k)) return maybe_k;
12066  }
12067 
12068  cache->set(EntryToIndex(entry), k);
12069  cache->set(EntryToIndex(entry) + 1, value);
12070  cache->ElementAdded();
12071  return cache;
12072 }
12073 
12074 
12076  JSRegExp::Flags flags,
12077  FixedArray* value) {
12078  RegExpKey key(src, flags);
12079  Object* obj;
12080  { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
12081  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12082  }
12083 
12084  CompilationCacheTable* cache =
12085  reinterpret_cast<CompilationCacheTable*>(obj);
12086  int entry = cache->FindInsertionEntry(key.Hash());
12087  // We store the value in the key slot, and compare the search key
12088  // to the stored value with a custon IsMatch function during lookups.
12089  cache->set(EntryToIndex(entry), value);
12090  cache->set(EntryToIndex(entry) + 1, value);
12091  cache->ElementAdded();
12092  return cache;
12093 }
12094 
12095 
12096 void CompilationCacheTable::Remove(Object* value) {
12097  Object* the_hole_value = GetHeap()->the_hole_value();
12098  for (int entry = 0, size = Capacity(); entry < size; entry++) {
12099  int entry_index = EntryToIndex(entry);
12100  int value_index = entry_index + 1;
12101  if (get(value_index) == value) {
12102  NoWriteBarrierSet(this, entry_index, the_hole_value);
12103  NoWriteBarrierSet(this, value_index, the_hole_value);
12104  ElementRemoved();
12105  }
12106  }
12107  return;
12108 }
12109 
12110 
12111 // SymbolsKey used for HashTable where key is array of symbols.
12112 class SymbolsKey : public HashTableKey {
12113  public:
12114  explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { }
12115 
12116  bool IsMatch(Object* symbols) {
12117  FixedArray* o = FixedArray::cast(symbols);
12118  int len = symbols_->length();
12119  if (o->length() != len) return false;
12120  for (int i = 0; i < len; i++) {
12121  if (o->get(i) != symbols_->get(i)) return false;
12122  }
12123  return true;
12124  }
12125 
12126  uint32_t Hash() { return HashForObject(symbols_); }
12127 
12128  uint32_t HashForObject(Object* obj) {
12129  FixedArray* symbols = FixedArray::cast(obj);
12130  int len = symbols->length();
12131  uint32_t hash = 0;
12132  for (int i = 0; i < len; i++) {
12133  hash ^= String::cast(symbols->get(i))->Hash();
12134  }
12135  return hash;
12136  }
12137 
12138  Object* AsObject() { return symbols_; }
12139 
12140  private:
12141  FixedArray* symbols_;
12142 };
12143 
12144 
12145 Object* MapCache::Lookup(FixedArray* array) {
12146  SymbolsKey key(array);
12147  int entry = FindEntry(&key);
12148  if (entry == kNotFound) return GetHeap()->undefined_value();
12149  return get(EntryToIndex(entry) + 1);
12150 }
12151 
12152 
12153 MaybeObject* MapCache::Put(FixedArray* array, Map* value) {
12154  SymbolsKey key(array);
12155  Object* obj;
12156  { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
12157  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12158  }
12159 
12160  MapCache* cache = reinterpret_cast<MapCache*>(obj);
12161  int entry = cache->FindInsertionEntry(key.Hash());
12162  cache->set(EntryToIndex(entry), array);
12163  cache->set(EntryToIndex(entry) + 1, value);
12164  cache->ElementAdded();
12165  return cache;
12166 }
12167 
12168 
12169 template<typename Shape, typename Key>
12170 MaybeObject* Dictionary<Shape, Key>::Allocate(int at_least_space_for) {
12171  Object* obj;
12172  { MaybeObject* maybe_obj =
12173  HashTable<Shape, Key>::Allocate(at_least_space_for);
12174  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12175  }
12176  // Initialize the next enumeration index.
12178  SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
12179  return obj;
12180 }
12181 
12182 
12183 template<typename Shape, typename Key>
12187 
12188  // Allocate and initialize iteration order array.
12189  Object* obj;
12190  { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12191  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12192  }
12193  FixedArray* iteration_order = FixedArray::cast(obj);
12194  for (int i = 0; i < length; i++) {
12195  iteration_order->set(i, Smi::FromInt(i));
12196  }
12197 
12198  // Allocate array with enumeration order.
12199  { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12200  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12201  }
12202  FixedArray* enumeration_order = FixedArray::cast(obj);
12203 
12204  // Fill the enumeration order array with property details.
12205  int capacity = HashTable<Shape, Key>::Capacity();
12206  int pos = 0;
12207  for (int i = 0; i < capacity; i++) {
12209  enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index()));
12210  }
12211  }
12212 
12213  // Sort the arrays wrt. enumeration order.
12214  iteration_order->SortPairs(enumeration_order, enumeration_order->length());
12215 
12216  // Overwrite the enumeration_order with the enumeration indices.
12217  for (int i = 0; i < length; i++) {
12218  int index = Smi::cast(iteration_order->get(i))->value();
12219  int enum_index = PropertyDetails::kInitialIndex + i;
12220  enumeration_order->set(index, Smi::FromInt(enum_index));
12221  }
12222 
12223  // Update the dictionary with new indices.
12224  capacity = HashTable<Shape, Key>::Capacity();
12225  pos = 0;
12226  for (int i = 0; i < capacity; i++) {
12228  int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
12229  PropertyDetails details = DetailsAt(i);
12230  PropertyDetails new_details =
12231  PropertyDetails(details.attributes(), details.type(), enum_index);
12232  DetailsAtPut(i, new_details);
12233  }
12234  }
12235 
12236  // Set the next enumeration index.
12237  SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
12238  return this;
12239 }
12240 
12241 template<typename Shape, typename Key>
12242 MaybeObject* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
12243  // Check whether there are enough enumeration indices to add n elements.
12244  if (Shape::kIsEnumerable &&
12245  !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
12246  // If not, we generate new indices for the properties.
12247  Object* result;
12248  { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
12249  if (!maybe_result->ToObject(&result)) return maybe_result;
12250  }
12251  }
12253 }
12254 
12255 
12256 template<typename Shape, typename Key>
12258  JSReceiver::DeleteMode mode) {
12260  PropertyDetails details = DetailsAt(entry);
12261  // Ignore attributes if forcing a deletion.
12262  if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
12263  return heap->false_value();
12264  }
12265  SetEntry(entry, heap->the_hole_value(), heap->the_hole_value());
12267  return heap->true_value();
12268 }
12269 
12270 
12271 template<typename Shape, typename Key>
12272 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) {
12273  return HashTable<Shape, Key>::Shrink(key);
12274 }
12275 
12276 
12277 template<typename Shape, typename Key>
12278 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
12279  int entry = this->FindEntry(key);
12280 
12281  // If the entry is present set the value;
12282  if (entry != Dictionary<Shape, Key>::kNotFound) {
12283  ValueAtPut(entry, value);
12284  return this;
12285  }
12286 
12287  // Check whether the dictionary should be extended.
12288  Object* obj;
12289  { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12290  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12291  }
12292 
12293  Object* k;
12294  { MaybeObject* maybe_k = Shape::AsObject(key);
12295  if (!maybe_k->ToObject(&k)) return maybe_k;
12296  }
12297  PropertyDetails details = PropertyDetails(NONE, NORMAL);
12298 
12299  return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
12301 }
12302 
12303 
12304 template<typename Shape, typename Key>
12305 MaybeObject* Dictionary<Shape, Key>::Add(Key key,
12306  Object* value,
12307  PropertyDetails details) {
12308  // Valdate key is absent.
12309  SLOW_ASSERT((this->FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
12310  // Check whether the dictionary should be extended.
12311  Object* obj;
12312  { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12313  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12314  }
12315 
12316  return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
12318 }
12319 
12320 
12321 // Add a key, value pair to the dictionary.
12322 template<typename Shape, typename Key>
12324  Object* value,
12325  PropertyDetails details,
12326  uint32_t hash) {
12327  // Compute the key object.
12328  Object* k;
12329  { MaybeObject* maybe_k = Shape::AsObject(key);
12330  if (!maybe_k->ToObject(&k)) return maybe_k;
12331  }
12332 
12333  uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
12334  // Insert element at empty or deleted entry
12335  if (!details.IsDeleted() && details.index() == 0 && Shape::kIsEnumerable) {
12336  // Assign an enumeration index to the property and update
12337  // SetNextEnumerationIndex.
12338  int index = NextEnumerationIndex();
12339  details = PropertyDetails(details.attributes(), details.type(), index);
12340  SetNextEnumerationIndex(index + 1);
12341  }
12342  SetEntry(entry, k, value, details);
12343  ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
12344  || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
12346  return this;
12347 }
12348 
12349 
12351  // If the dictionary requires slow elements an element has already
12352  // been added at a high index.
12353  if (requires_slow_elements()) return;
12354  // Check if this index is high enough that we should require slow
12355  // elements.
12356  if (key > kRequiresSlowElementsLimit) {
12357  set_requires_slow_elements();
12358  return;
12359  }
12360  // Update max key value.
12361  Object* max_index_object = get(kMaxNumberKeyIndex);
12362  if (!max_index_object->IsSmi() || max_number_key() < key) {
12363  FixedArray::set(kMaxNumberKeyIndex,
12364  Smi::FromInt(key << kRequiresSlowElementsTagSize));
12365  }
12366 }
12367 
12368 
12369 MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key,
12370  Object* value,
12371  PropertyDetails details) {
12372  UpdateMaxNumberKey(key);
12373  SLOW_ASSERT(this->FindEntry(key) == kNotFound);
12374  return Add(key, value, details);
12375 }
12376 
12377 
12379  Object* value) {
12380  SLOW_ASSERT(this->FindEntry(key) == kNotFound);
12381  return Add(key, value, PropertyDetails(NONE, NORMAL));
12382 }
12383 
12384 
12385 MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) {
12386  UpdateMaxNumberKey(key);
12387  return AtPut(key, value);
12388 }
12389 
12390 
12391 MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key,
12392  Object* value) {
12393  return AtPut(key, value);
12394 }
12395 
12396 
12398  Handle<SeededNumberDictionary> dictionary,
12399  uint32_t index,
12400  Handle<Object> value,
12401  PropertyDetails details) {
12402  CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
12403  dictionary->Set(index, *value, details),
12405 }
12406 
12407 
12410  uint32_t index,
12411  Handle<Object> value) {
12412  CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
12413  dictionary->Set(index, *value),
12415 }
12416 
12417 
12418 MaybeObject* SeededNumberDictionary::Set(uint32_t key,
12419  Object* value,
12420  PropertyDetails details) {
12421  int entry = FindEntry(key);
12422  if (entry == kNotFound) return AddNumberEntry(key, value, details);
12423  // Preserve enumeration index.
12424  details = PropertyDetails(details.attributes(),
12425  details.type(),
12426  DetailsAt(entry).index());
12427  MaybeObject* maybe_object_key = SeededNumberDictionaryShape::AsObject(key);
12428  Object* object_key;
12429  if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
12430  SetEntry(entry, object_key, value, details);
12431  return this;
12432 }
12433 
12434 
12435 MaybeObject* UnseededNumberDictionary::Set(uint32_t key,
12436  Object* value) {
12437  int entry = FindEntry(key);
12438  if (entry == kNotFound) return AddNumberEntry(key, value);
12439  MaybeObject* maybe_object_key = UnseededNumberDictionaryShape::AsObject(key);
12440  Object* object_key;
12441  if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
12442  SetEntry(entry, object_key, value);
12443  return this;
12444 }
12445 
12446 
12447 
12448 template<typename Shape, typename Key>
12450  PropertyAttributes filter) {
12451  int capacity = HashTable<Shape, Key>::Capacity();
12452  int result = 0;
12453  for (int i = 0; i < capacity; i++) {
12454  Object* k = HashTable<Shape, Key>::KeyAt(i);
12456  PropertyDetails details = DetailsAt(i);
12457  if (details.IsDeleted()) continue;
12458  PropertyAttributes attr = details.attributes();
12459  if ((attr & filter) == 0) result++;
12460  }
12461  }
12462  return result;
12463 }
12464 
12465 
12466 template<typename Shape, typename Key>
12468  return NumberOfElementsFilterAttributes(
12469  static_cast<PropertyAttributes>(DONT_ENUM));
12470 }
12471 
12472 
12473 template<typename Shape, typename Key>
12475  FixedArray* storage,
12476  PropertyAttributes filter,
12477  typename Dictionary<Shape, Key>::SortMode sort_mode) {
12478  ASSERT(storage->length() >= NumberOfEnumElements());
12479  int capacity = HashTable<Shape, Key>::Capacity();
12480  int index = 0;
12481  for (int i = 0; i < capacity; i++) {
12482  Object* k = HashTable<Shape, Key>::KeyAt(i);
12484  PropertyDetails details = DetailsAt(i);
12485  if (details.IsDeleted()) continue;
12486  PropertyAttributes attr = details.attributes();
12487  if ((attr & filter) == 0) storage->set(index++, k);
12488  }
12489  }
12490  if (sort_mode == Dictionary<Shape, Key>::SORTED) {
12491  storage->SortPairs(storage, index);
12492  }
12493  ASSERT(storage->length() >= index);
12494 }
12495 
12496 
12498  FixedArray* sort_array) {
12499  ASSERT(storage->length() >= NumberOfEnumElements());
12500  int capacity = Capacity();
12501  int index = 0;
12502  for (int i = 0; i < capacity; i++) {
12503  Object* k = KeyAt(i);
12504  if (IsKey(k)) {
12505  PropertyDetails details = DetailsAt(i);
12506  if (details.IsDeleted() || details.IsDontEnum()) continue;
12507  storage->set(index, k);
12508  sort_array->set(index, Smi::FromInt(details.index()));
12509  index++;
12510  }
12511  }
12512  storage->SortPairs(sort_array, sort_array->length());
12513  ASSERT(storage->length() >= index);
12514 }
12515 
12516 
12517 template<typename Shape, typename Key>
12519  FixedArray* storage,
12520  int index,
12521  typename Dictionary<Shape, Key>::SortMode sort_mode) {
12522  ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
12523  static_cast<PropertyAttributes>(NONE)));
12524  int capacity = HashTable<Shape, Key>::Capacity();
12525  for (int i = 0; i < capacity; i++) {
12526  Object* k = HashTable<Shape, Key>::KeyAt(i);
12528  PropertyDetails details = DetailsAt(i);
12529  if (details.IsDeleted()) continue;
12530  storage->set(index++, k);
12531  }
12532  }
12533  if (sort_mode == Dictionary<Shape, Key>::SORTED) {
12534  storage->SortPairs(storage, index);
12535  }
12536  ASSERT(storage->length() >= index);
12537 }
12538 
12539 
12540 // Backwards lookup (slow).
12541 template<typename Shape, typename Key>
12543  int capacity = HashTable<Shape, Key>::Capacity();
12544  for (int i = 0; i < capacity; i++) {
12545  Object* k = HashTable<Shape, Key>::KeyAt(i);
12547  Object* e = ValueAt(i);
12548  if (e->IsJSGlobalPropertyCell()) {
12549  e = JSGlobalPropertyCell::cast(e)->value();
12550  }
12551  if (e == value) return k;
12552  }
12553  }
12555  return heap->undefined_value();
12556 }
12557 
12558 
12560  JSObject* obj, int unused_property_fields) {
12561  // Make sure we preserve dictionary representation if there are too many
12562  // descriptors.
12563  if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj;
12564 
12565  // Figure out if it is necessary to generate new enumeration indices.
12566  int max_enumeration_index =
12567  NextEnumerationIndex() +
12569  NumberOfElements());
12570  if (!PropertyDetails::IsValidIndex(max_enumeration_index)) {
12571  Object* result;
12572  { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
12573  if (!maybe_result->ToObject(&result)) return maybe_result;
12574  }
12575  }
12576 
12577  int instance_descriptor_length = 0;
12578  int number_of_fields = 0;
12579 
12580  Heap* heap = GetHeap();
12581 
12582  // Compute the length of the instance descriptor.
12583  int capacity = Capacity();
12584  for (int i = 0; i < capacity; i++) {
12585  Object* k = KeyAt(i);
12586  if (IsKey(k)) {
12587  Object* value = ValueAt(i);
12588  PropertyType type = DetailsAt(i).type();
12589  ASSERT(type != FIELD);
12590  instance_descriptor_length++;
12591  if (type == NORMAL &&
12592  (!value->IsJSFunction() || heap->InNewSpace(value))) {
12593  number_of_fields += 1;
12594  }
12595  }
12596  }
12597 
12598  // Allocate the instance descriptor.
12599  DescriptorArray* descriptors;
12600  { MaybeObject* maybe_descriptors =
12601  DescriptorArray::Allocate(instance_descriptor_length,
12603  if (!maybe_descriptors->To<DescriptorArray>(&descriptors)) {
12604  return maybe_descriptors;
12605  }
12606  }
12607 
12608  DescriptorArray::WhitenessWitness witness(descriptors);
12609 
12610  int inobject_props = obj->map()->inobject_properties();
12611  int number_of_allocated_fields =
12612  number_of_fields + unused_property_fields - inobject_props;
12613  if (number_of_allocated_fields < 0) {
12614  // There is enough inobject space for all fields (including unused).
12615  number_of_allocated_fields = 0;
12616  unused_property_fields = inobject_props - number_of_fields;
12617  }
12618 
12619  // Allocate the fixed array for the fields.
12620  Object* fields;
12621  { MaybeObject* maybe_fields =
12622  heap->AllocateFixedArray(number_of_allocated_fields);
12623  if (!maybe_fields->ToObject(&fields)) return maybe_fields;
12624  }
12625 
12626  // Fill in the instance descriptor and the fields.
12627  int next_descriptor = 0;
12628  int current_offset = 0;
12629  for (int i = 0; i < capacity; i++) {
12630  Object* k = KeyAt(i);
12631  if (IsKey(k)) {
12632  Object* value = ValueAt(i);
12633  // Ensure the key is a symbol before writing into the instance descriptor.
12634  Object* key;
12635  { MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k));
12636  if (!maybe_key->ToObject(&key)) return maybe_key;
12637  }
12638  PropertyDetails details = DetailsAt(i);
12639  PropertyType type = details.type();
12640 
12641  if (value->IsJSFunction() && !heap->InNewSpace(value)) {
12643  JSFunction::cast(value),
12644  details.attributes(),
12645  details.index());
12646  descriptors->Set(next_descriptor++, &d, witness);
12647  } else if (type == NORMAL) {
12648  if (current_offset < inobject_props) {
12649  obj->InObjectPropertyAtPut(current_offset,
12650  value,
12652  } else {
12653  int offset = current_offset - inobject_props;
12654  FixedArray::cast(fields)->set(offset, value);
12655  }
12657  current_offset++,
12658  details.attributes(),
12659  details.index());
12660  descriptors->Set(next_descriptor++, &d, witness);
12661  } else if (type == CALLBACKS) {
12662  if (value->IsAccessorPair()) {
12663  MaybeObject* maybe_copy =
12665  if (!maybe_copy->To(&value)) return maybe_copy;
12666  }
12668  value,
12669  details.attributes(),
12670  details.index());
12671  descriptors->Set(next_descriptor++, &d, witness);
12672  } else {
12673  UNREACHABLE();
12674  }
12675  }
12676  }
12677  ASSERT(current_offset == number_of_fields);
12678 
12679  descriptors->Sort(witness);
12680  // Allocate new map.
12681  Object* new_map;
12682  { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
12683  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
12684  }
12685 
12686  // Transform the object.
12687  obj->set_map(Map::cast(new_map));
12688  obj->map()->set_instance_descriptors(descriptors);
12689  obj->map()->set_unused_property_fields(unused_property_fields);
12690 
12691  obj->set_properties(FixedArray::cast(fields));
12692  ASSERT(obj->IsJSObject());
12693 
12694  descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
12695  // Check that it really works.
12696  ASSERT(obj->HasFastProperties());
12697 
12698  return obj;
12699 }
12700 
12701 
12702 bool ObjectHashSet::Contains(Object* key) {
12703  ASSERT(IsKey(key));
12704 
12705  // If the object does not have an identity hash, it was never used as a key.
12706  { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12707  if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return false;
12708  }
12709  return (FindEntry(key) != kNotFound);
12710 }
12711 
12712 
12713 MaybeObject* ObjectHashSet::Add(Object* key) {
12714  ASSERT(IsKey(key));
12715 
12716  // Make sure the key object has an identity hash code.
12717  int hash;
12718  { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
12719  if (maybe_hash->IsFailure()) return maybe_hash;
12720  hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
12721  }
12722  int entry = FindEntry(key);
12723 
12724  // Check whether key is already present.
12725  if (entry != kNotFound) return this;
12726 
12727  // Check whether the hash set should be extended and add entry.
12728  Object* obj;
12729  { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12730  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12731  }
12732  ObjectHashSet* table = ObjectHashSet::cast(obj);
12733  entry = table->FindInsertionEntry(hash);
12734  table->set(EntryToIndex(entry), key);
12735  table->ElementAdded();
12736  return table;
12737 }
12738 
12739 
12740 MaybeObject* ObjectHashSet::Remove(Object* key) {
12741  ASSERT(IsKey(key));
12742 
12743  // If the object does not have an identity hash, it was never used as a key.
12744  { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12745  if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return this;
12746  }
12747  int entry = FindEntry(key);
12748 
12749  // Check whether key is actually present.
12750  if (entry == kNotFound) return this;
12751 
12752  // Remove entry and try to shrink this hash set.
12753  set_the_hole(EntryToIndex(entry));
12754  ElementRemoved();
12755  return Shrink(key);
12756 }
12757 
12758 
12759 Object* ObjectHashTable::Lookup(Object* key) {
12760  ASSERT(IsKey(key));
12761 
12762  // If the object does not have an identity hash, it was never used as a key.
12763  { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12764  if (maybe_hash->ToObjectUnchecked()->IsUndefined()) {
12765  return GetHeap()->undefined_value();
12766  }
12767  }
12768  int entry = FindEntry(key);
12769  if (entry == kNotFound) return GetHeap()->undefined_value();
12770  return get(EntryToIndex(entry) + 1);
12771 }
12772 
12773 
12774 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) {
12775  ASSERT(IsKey(key));
12776 
12777  // Make sure the key object has an identity hash code.
12778  int hash;
12779  { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
12780  if (maybe_hash->IsFailure()) return maybe_hash;
12781  hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
12782  }
12783  int entry = FindEntry(key);
12784 
12785  // Check whether to perform removal operation.
12786  if (value->IsUndefined()) {
12787  if (entry == kNotFound) return this;
12788  RemoveEntry(entry);
12789  return Shrink(key);
12790  }
12791 
12792  // Key is already in table, just overwrite value.
12793  if (entry != kNotFound) {
12794  set(EntryToIndex(entry) + 1, value);
12795  return this;
12796  }
12797 
12798  // Check whether the hash table should be extended.
12799  Object* obj;
12800  { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12801  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12802  }
12803  ObjectHashTable* table = ObjectHashTable::cast(obj);
12804  table->AddEntry(table->FindInsertionEntry(hash), key, value);
12805  return table;
12806 }
12807 
12808 
12809 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
12810  set(EntryToIndex(entry), key);
12811  set(EntryToIndex(entry) + 1, value);
12812  ElementAdded();
12813 }
12814 
12815 
12816 void ObjectHashTable::RemoveEntry(int entry) {
12817  set_the_hole(EntryToIndex(entry));
12818  set_the_hole(EntryToIndex(entry) + 1);
12819  ElementRemoved();
12820 }
12821 
12822 
12823 #ifdef ENABLE_DEBUGGER_SUPPORT
12824 // Check if there is a break point at this code position.
12825 bool DebugInfo::HasBreakPoint(int code_position) {
12826  // Get the break point info object for this code position.
12827  Object* break_point_info = GetBreakPointInfo(code_position);
12828 
12829  // If there is no break point info object or no break points in the break
12830  // point info object there is no break point at this code position.
12831  if (break_point_info->IsUndefined()) return false;
12832  return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
12833 }
12834 
12835 
12836 // Get the break point info object for this code position.
12837 Object* DebugInfo::GetBreakPointInfo(int code_position) {
12838  // Find the index of the break point info object for this code position.
12839  int index = GetBreakPointInfoIndex(code_position);
12840 
12841  // Return the break point info object if any.
12842  if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
12843  return BreakPointInfo::cast(break_points()->get(index));
12844 }
12845 
12846 
12847 // Clear a break point at the specified code position.
12848 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
12849  int code_position,
12850  Handle<Object> break_point_object) {
12851  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
12852  if (break_point_info->IsUndefined()) return;
12853  BreakPointInfo::ClearBreakPoint(
12854  Handle<BreakPointInfo>::cast(break_point_info),
12855  break_point_object);
12856 }
12857 
12858 
12859 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
12860  int code_position,
12861  int source_position,
12862  int statement_position,
12863  Handle<Object> break_point_object) {
12864  Isolate* isolate = Isolate::Current();
12865  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
12866  if (!break_point_info->IsUndefined()) {
12867  BreakPointInfo::SetBreakPoint(
12868  Handle<BreakPointInfo>::cast(break_point_info),
12869  break_point_object);
12870  return;
12871  }
12872 
12873  // Adding a new break point for a code position which did not have any
12874  // break points before. Try to find a free slot.
12875  int index = kNoBreakPointInfo;
12876  for (int i = 0; i < debug_info->break_points()->length(); i++) {
12877  if (debug_info->break_points()->get(i)->IsUndefined()) {
12878  index = i;
12879  break;
12880  }
12881  }
12882  if (index == kNoBreakPointInfo) {
12883  // No free slot - extend break point info array.
12884  Handle<FixedArray> old_break_points =
12885  Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
12886  Handle<FixedArray> new_break_points =
12887  isolate->factory()->NewFixedArray(
12888  old_break_points->length() +
12889  Debug::kEstimatedNofBreakPointsInFunction);
12890 
12891  debug_info->set_break_points(*new_break_points);
12892  for (int i = 0; i < old_break_points->length(); i++) {
12893  new_break_points->set(i, old_break_points->get(i));
12894  }
12895  index = old_break_points->length();
12896  }
12897  ASSERT(index != kNoBreakPointInfo);
12898 
12899  // Allocate new BreakPointInfo object and set the break point.
12900  Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
12901  isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
12902  new_break_point_info->set_code_position(Smi::FromInt(code_position));
12903  new_break_point_info->set_source_position(Smi::FromInt(source_position));
12904  new_break_point_info->
12905  set_statement_position(Smi::FromInt(statement_position));
12906  new_break_point_info->set_break_point_objects(
12907  isolate->heap()->undefined_value());
12908  BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
12909  debug_info->break_points()->set(index, *new_break_point_info);
12910 }
12911 
12912 
12913 // Get the break point objects for a code position.
12914 Object* DebugInfo::GetBreakPointObjects(int code_position) {
12915  Object* break_point_info = GetBreakPointInfo(code_position);
12916  if (break_point_info->IsUndefined()) {
12917  return GetHeap()->undefined_value();
12918  }
12919  return BreakPointInfo::cast(break_point_info)->break_point_objects();
12920 }
12921 
12922 
12923 // Get the total number of break points.
12924 int DebugInfo::GetBreakPointCount() {
12925  if (break_points()->IsUndefined()) return 0;
12926  int count = 0;
12927  for (int i = 0; i < break_points()->length(); i++) {
12928  if (!break_points()->get(i)->IsUndefined()) {
12929  BreakPointInfo* break_point_info =
12930  BreakPointInfo::cast(break_points()->get(i));
12931  count += break_point_info->GetBreakPointCount();
12932  }
12933  }
12934  return count;
12935 }
12936 
12937 
12938 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
12939  Handle<Object> break_point_object) {
12940  Heap* heap = debug_info->GetHeap();
12941  if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
12942  for (int i = 0; i < debug_info->break_points()->length(); i++) {
12943  if (!debug_info->break_points()->get(i)->IsUndefined()) {
12944  Handle<BreakPointInfo> break_point_info =
12945  Handle<BreakPointInfo>(BreakPointInfo::cast(
12946  debug_info->break_points()->get(i)));
12947  if (BreakPointInfo::HasBreakPointObject(break_point_info,
12948  break_point_object)) {
12949  return *break_point_info;
12950  }
12951  }
12952  }
12953  return heap->undefined_value();
12954 }
12955 
12956 
12957 // Find the index of the break point info object for the specified code
12958 // position.
12959 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
12960  if (break_points()->IsUndefined()) return kNoBreakPointInfo;
12961  for (int i = 0; i < break_points()->length(); i++) {
12962  if (!break_points()->get(i)->IsUndefined()) {
12963  BreakPointInfo* break_point_info =
12964  BreakPointInfo::cast(break_points()->get(i));
12965  if (break_point_info->code_position()->value() == code_position) {
12966  return i;
12967  }
12968  }
12969  }
12970  return kNoBreakPointInfo;
12971 }
12972 
12973 
12974 // Remove the specified break point object.
12975 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
12976  Handle<Object> break_point_object) {
12977  Isolate* isolate = Isolate::Current();
12978  // If there are no break points just ignore.
12979  if (break_point_info->break_point_objects()->IsUndefined()) return;
12980  // If there is a single break point clear it if it is the same.
12981  if (!break_point_info->break_point_objects()->IsFixedArray()) {
12982  if (break_point_info->break_point_objects() == *break_point_object) {
12983  break_point_info->set_break_point_objects(
12984  isolate->heap()->undefined_value());
12985  }
12986  return;
12987  }
12988  // If there are multiple break points shrink the array
12989  ASSERT(break_point_info->break_point_objects()->IsFixedArray());
12990  Handle<FixedArray> old_array =
12991  Handle<FixedArray>(
12992  FixedArray::cast(break_point_info->break_point_objects()));
12993  Handle<FixedArray> new_array =
12994  isolate->factory()->NewFixedArray(old_array->length() - 1);
12995  int found_count = 0;
12996  for (int i = 0; i < old_array->length(); i++) {
12997  if (old_array->get(i) == *break_point_object) {
12998  ASSERT(found_count == 0);
12999  found_count++;
13000  } else {
13001  new_array->set(i - found_count, old_array->get(i));
13002  }
13003  }
13004  // If the break point was found in the list change it.
13005  if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
13006 }
13007 
13008 
13009 // Add the specified break point object.
13010 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
13011  Handle<Object> break_point_object) {
13012  // If there was no break point objects before just set it.
13013  if (break_point_info->break_point_objects()->IsUndefined()) {
13014  break_point_info->set_break_point_objects(*break_point_object);
13015  return;
13016  }
13017  // If the break point object is the same as before just ignore.
13018  if (break_point_info->break_point_objects() == *break_point_object) return;
13019  // If there was one break point object before replace with array.
13020  if (!break_point_info->break_point_objects()->IsFixedArray()) {
13021  Handle<FixedArray> array = FACTORY->NewFixedArray(2);
13022  array->set(0, break_point_info->break_point_objects());
13023  array->set(1, *break_point_object);
13024  break_point_info->set_break_point_objects(*array);
13025  return;
13026  }
13027  // If there was more than one break point before extend array.
13028  Handle<FixedArray> old_array =
13029  Handle<FixedArray>(
13030  FixedArray::cast(break_point_info->break_point_objects()));
13031  Handle<FixedArray> new_array =
13032  FACTORY->NewFixedArray(old_array->length() + 1);
13033  for (int i = 0; i < old_array->length(); i++) {
13034  // If the break point was there before just ignore.
13035  if (old_array->get(i) == *break_point_object) return;
13036  new_array->set(i, old_array->get(i));
13037  }
13038  // Add the new break point.
13039  new_array->set(old_array->length(), *break_point_object);
13040  break_point_info->set_break_point_objects(*new_array);
13041 }
13042 
13043 
13044 bool BreakPointInfo::HasBreakPointObject(
13045  Handle<BreakPointInfo> break_point_info,
13046  Handle<Object> break_point_object) {
13047  // No break point.
13048  if (break_point_info->break_point_objects()->IsUndefined()) return false;
13049  // Single break point.
13050  if (!break_point_info->break_point_objects()->IsFixedArray()) {
13051  return break_point_info->break_point_objects() == *break_point_object;
13052  }
13053  // Multiple break points.
13054  FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
13055  for (int i = 0; i < array->length(); i++) {
13056  if (array->get(i) == *break_point_object) {
13057  return true;
13058  }
13059  }
13060  return false;
13061 }
13062 
13063 
13064 // Get the number of break points.
13065 int BreakPointInfo::GetBreakPointCount() {
13066  // No break point.
13067  if (break_point_objects()->IsUndefined()) return 0;
13068  // Single break point.
13069  if (!break_point_objects()->IsFixedArray()) return 1;
13070  // Multiple break points.
13071  return FixedArray::cast(break_point_objects())->length();
13072 }
13073 #endif // ENABLE_DEBUGGER_SUPPORT
13074 
13075 
13076 Object* JSDate::GetField(Object* object, Smi* index) {
13077  return JSDate::cast(object)->DoGetField(
13078  static_cast<FieldIndex>(index->value()));
13079 }
13080 
13081 
13082 Object* JSDate::DoGetField(FieldIndex index) {
13083  ASSERT(index != kDateValue);
13084 
13085  DateCache* date_cache = GetIsolate()->date_cache();
13086 
13087  if (index < kFirstUncachedField) {
13088  Object* stamp = cache_stamp();
13089  if (stamp != date_cache->stamp() && stamp->IsSmi()) {
13090  // Since the stamp is not NaN, the value is also not NaN.
13091  int64_t local_time_ms =
13092  date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
13093  SetLocalFields(local_time_ms, date_cache);
13094  }
13095  switch (index) {
13096  case kYear: return year();
13097  case kMonth: return month();
13098  case kDay: return day();
13099  case kWeekday: return weekday();
13100  case kHour: return hour();
13101  case kMinute: return min();
13102  case kSecond: return sec();
13103  default: UNREACHABLE();
13104  }
13105  }
13106 
13107  if (index >= kFirstUTCField) {
13108  return GetUTCField(index, value()->Number(), date_cache);
13109  }
13110 
13111  double time = value()->Number();
13112  if (isnan(time)) return GetIsolate()->heap()->nan_value();
13113 
13114  int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
13115  int days = DateCache::DaysFromTime(local_time_ms);
13116 
13117  if (index == kDays) return Smi::FromInt(days);
13118 
13119  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
13120  if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
13121  ASSERT(index == kTimeInDay);
13122  return Smi::FromInt(time_in_day_ms);
13123 }
13124 
13125 
13126 Object* JSDate::GetUTCField(FieldIndex index,
13127  double value,
13128  DateCache* date_cache) {
13129  ASSERT(index >= kFirstUTCField);
13130 
13131  if (isnan(value)) return GetIsolate()->heap()->nan_value();
13132 
13133  int64_t time_ms = static_cast<int64_t>(value);
13134 
13135  if (index == kTimezoneOffset) {
13136  return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
13137  }
13138 
13139  int days = DateCache::DaysFromTime(time_ms);
13140 
13141  if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
13142 
13143  if (index <= kDayUTC) {
13144  int year, month, day;
13145  date_cache->YearMonthDayFromDays(days, &year, &month, &day);
13146  if (index == kYearUTC) return Smi::FromInt(year);
13147  if (index == kMonthUTC) return Smi::FromInt(month);
13148  ASSERT(index == kDayUTC);
13149  return Smi::FromInt(day);
13150  }
13151 
13152  int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
13153  switch (index) {
13154  case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
13155  case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
13156  case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
13157  case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
13158  case kDaysUTC: return Smi::FromInt(days);
13159  case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
13160  default: UNREACHABLE();
13161  }
13162 
13163  UNREACHABLE();
13164  return NULL;
13165 }
13166 
13167 
13168 void JSDate::SetValue(Object* value, bool is_value_nan) {
13169  set_value(value);
13170  if (is_value_nan) {
13171  HeapNumber* nan = GetIsolate()->heap()->nan_value();
13172  set_cache_stamp(nan, SKIP_WRITE_BARRIER);
13173  set_year(nan, SKIP_WRITE_BARRIER);
13174  set_month(nan, SKIP_WRITE_BARRIER);
13175  set_day(nan, SKIP_WRITE_BARRIER);
13176  set_hour(nan, SKIP_WRITE_BARRIER);
13177  set_min(nan, SKIP_WRITE_BARRIER);
13178  set_sec(nan, SKIP_WRITE_BARRIER);
13179  set_weekday(nan, SKIP_WRITE_BARRIER);
13180  } else {
13182  }
13183 }
13184 
13185 
13186 void JSDate::SetLocalFields(int64_t local_time_ms, DateCache* date_cache) {
13187  int days = DateCache::DaysFromTime(local_time_ms);
13188  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
13189  int year, month, day;
13190  date_cache->YearMonthDayFromDays(days, &year, &month, &day);
13191  int weekday = date_cache->Weekday(days);
13192  int hour = time_in_day_ms / (60 * 60 * 1000);
13193  int min = (time_in_day_ms / (60 * 1000)) % 60;
13194  int sec = (time_in_day_ms / 1000) % 60;
13195  set_cache_stamp(date_cache->stamp());
13196  set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13197  set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13198  set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13199  set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13200  set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13201  set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13202  set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13203 }
13204 
13205 } } // namespace v8::internal
static bool IsBlack(MarkBit mark_bit)
Definition: mark-compact.h:70
Object * GetPrototype()
Definition: objects.cc:709
byte * Address
Definition: globals.h:172
MUST_USE_RESULT MaybeObject * GetElementWithReceiver(Object *receiver, uint32_t index)
Definition: objects.cc:651
bool FLAG_enable_slow_asserts
MUST_USE_RESULT MaybeObject * GetElementWithInterceptor(Object *receiver, uint32_t index)
Definition: objects.cc:9955
void SetEnumCache(FixedArray *bridge_storage, FixedArray *new_cache, Object *new_index_cache)
Definition: objects.cc:5782
MUST_USE_RESULT MaybeObject * LookupAsciiSymbol(Vector< const char > str, Object **s)
Definition: objects.cc:11941
void ClearTypeFeedbackCells(Heap *heap)
Definition: objects.cc:8258
Object * Lookup(MapHandleList *maps, int code_kind)
Definition: objects.cc:5645
int IndexInCodeCache(Object *name, Code *code)
Definition: objects.cc:4971
bool IsMatch(Object *string)
Definition: objects.cc:10937
void set_elements_kind(ElementsKind elements_kind)
Definition: objects.h:4677
bool IsIdentifierPart(unibrow::uchar c)
Definition: scanner.h:155
void SetBackPointer(Object *value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
Definition: objects-inl.h:3512
StringKey(String *string)
Definition: objects.cc:10693
static Handle< Object > DeleteElement(Handle< JSObject > obj, uint32_t index)
Definition: objects.cc:3791
Object * KeyAt(int entry)
Definition: objects.h:2816
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:1944
int LinearSearch(SearchMode mode, String *name, int len)
Definition: objects.cc:6053
Code * builtin(Name name)
Definition: builtins.h:312
PropertyAttributes GetPropertyAttribute(String *name)
Definition: objects-inl.h:4778
static const int kDefaultMaxOptCount
Definition: compiler.h:276
static const int kGenerousAllocationCount
Definition: objects.h:5302
JSGlobalPropertyCell * Cell(int index)
Definition: objects-inl.h:5047
Object * get(AccessorComponent component)
Definition: objects.h:8222
#define SLOW_ASSERT(condition)
Definition: checks.h:276
static bool CompileLazy(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: objects.cc:7465
static DeoptimizationOutputData * cast(Object *obj)
uint32_t HashForObject(Object *other)
Definition: objects.cc:10708
void CopyValuesTo(FixedArray *elements)
Definition: objects.cc:10187
virtual void Seek(unsigned pos)
Definition: objects.cc:6604
DateCache * date_cache()
Definition: isolate.h:1038
Object * Lookup(String *name, Code::Flags flags)
Definition: objects.cc:5325
#define CHECK_EQ(expected, value)
Definition: checks.h:219
static uchar LeadSurrogate(int char_code)
Definition: unicode.h:143
bool IsHoleyElementsKind(ElementsKind kind)
static const int kCodeEntryOffset
Definition: objects.h:5981
Object * LookupAccessor(String *name, AccessorComponent component)
Definition: objects.cc:4764
MUST_USE_RESULT MaybeObject * AllocateFixedArray(int length, PretenureFlag pretenure)
Definition: heap.cc:4712
static const int kArrayIndexHashMask
Definition: objects.h:7144
void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset, unsigned chars)
Definition: objects.cc:6435
void InvalidateRelocation()
Definition: objects.cc:8107
uint32_t HashForObject(Object *obj)
Definition: objects.cc:10832
void AddCharacter(uint32_t c)
Definition: objects-inl.h:4673
static const int kZeroHash
Definition: objects.h:7163
const char * ToCString(const v8::String::Utf8Value &value)
void set_has_deoptimization_support(bool value)
Definition: objects-inl.h:3107
virtual uint32_t Hash()=0
Object * LookupRegExp(String *source, JSRegExp::Flags flags)
Definition: objects.cc:12020
Handle< Value >(* NamedPropertySetter)(Local< String > property, Local< Value > value, const AccessorInfo &info)
Definition: v8.h:2031
uint32_t HashForObject(Object *obj)
Definition: objects.cc:12128
MUST_USE_RESULT MaybeObject * CopyDropDescriptors()
Definition: objects.cc:4839
#define RETURN_IF_SCHEDULED_EXCEPTION(isolate)
Definition: isolate.h:111
bool is_hidden_prototype()
Definition: objects.h:4629
void set(int index, Object *value)
Definition: objects-inl.h:1695
MUST_USE_RESULT MaybeObject * TransformPropertiesToFastFor(JSObject *obj, int unused_property_fields)
Definition: objects.cc:12559
void AddSurrogatePair(uc32 c)
Definition: objects.cc:7236
MUST_USE_RESULT MaybeObject * AddProperty(String *name, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:1719
void PrintF(const char *format,...)
Definition: v8utils.cc:40
MUST_USE_RESULT MaybeObject * GetPropertyWithCallback(Object *receiver, Object *structure, String *name)
Definition: objects.cc:162
virtual MUST_USE_RESULT MaybeObject * Delete(JSObject *holder, uint32_t key, JSReceiver::DeleteMode mode)=0
bool InNewSpace(Object *object)
Definition: heap-inl.h:292
unsigned stack_slots()
Definition: objects-inl.h:3171
bool EquivalentToForNormalization(Map *other, PropertyNormalizationMode mode)
Definition: objects.cc:7404
static TypeFeedbackInfo * cast(Object *obj)
static String * cast(Object *obj)
MUST_USE_RESULT MaybeObject * Add(Key key, Object *value, PropertyDetails details)
Definition: objects.cc:12305
void SortUnchecked(const WhitenessWitness &)
Definition: objects.cc:5967
StringSharedKey(String *source, SharedFunctionInfo *shared, LanguageMode language_mode, int scope_position)
Definition: objects.cc:10720
void SetValue(Object *value, bool is_value_nan)
Definition: objects.cc:13168
void DetailsAtPut(int entry, PropertyDetails value)
Definition: objects.h:3056
MUST_USE_RESULT MaybeObject * SetPropertyWithDefinedSetter(JSReceiver *setter, Object *value)
Definition: objects.cc:2046
int Lookup(DescriptorArray *array, String *name)
Definition: heap.h:2287
MUST_USE_RESULT MaybeObject * AllocateSubString(String *buffer, int start, int end, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:3233
void SetThisPropertyAssignmentsInfo(bool has_only_simple_this_property_assignments, FixedArray *this_property_assignments)
Definition: objects.cc:7746
MaybeObject * TryFlatten(PretenureFlag pretenure=NOT_TENURED)
Definition: objects-inl.h:2284
MUST_USE_RESULT PropertyAttributes GetElementAttributeWithHandler(JSReceiver *receiver, uint32_t index)
Definition: objects.cc:2728
MUST_USE_RESULT MaybeObject * PrepareSlowElementsForSort(uint32_t limit)
Definition: objects.cc:11390
const uint32_t kTwoByteStringTag
Definition: objects.h:450
uint32_t NumberToUint32(Object *number)
Definition: v8conversions.h:43
bool HasRealElementProperty(uint32_t index)
Definition: objects.cc:10310
void set_opt_count(int opt_count)
unsigned Utf16Length()
Definition: unicode.cc:342
uint32_t HashForObject(Object *other)
Definition: objects.cc:11043
static DescriptorArray * cast(Object *obj)
static Failure * InternalError()
Definition: objects-inl.h:1011
static void CopyFrom(Handle< DescriptorArray > dst, int dst_index, Handle< DescriptorArray > src, int src_index, const WhitenessWitness &witness)
Definition: objects.cc:5811
void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6274
int NumberOfLocalElements(PropertyAttributes filter)
Definition: objects.cc:10529
Object * ToBoolean(bool condition)
Definition: heap-inl.h:641
void clear_instance_descriptors()
Definition: objects-inl.h:3424
void DeleteHiddenProperty(String *key)
Definition: objects.cc:3598
Isolate * isolate()
Definition: heap-inl.h:494
int unused_property_fields()
Definition: objects-inl.h:2874
void set_length(Smi *length)
Definition: objects-inl.h:4991
void SourceCodePrint(StringStream *accumulator, int max_length)
Definition: objects.cc:7804
PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject *receiver, String *name, bool continue_search)
Definition: objects.cc:3033
MUST_USE_RESULT MaybeObject * Put(MapHandleList *maps, int code_kind, Code *code)
Definition: objects.cc:5654
static const char * Name(Value tok)
Definition: token.h:196
static Smi * FromInt(int value)
Definition: objects-inl.h:973
bool IsFastObjectElementsKind(ElementsKind kind)
bool allowed_in_shared_map_code_cache()
Definition: objects.cc:8272
void IteratePointer(ObjectVisitor *v, int offset)
Definition: objects-inl.h:1185
NormalizedMapSharingMode
Definition: objects.h:160
#define LOG(isolate, Call)
Definition: log.h:81
RegExpKey(String *string, JSRegExp::Flags flags)
Definition: objects.cc:10809
unsigned stack_check_table_offset()
Definition: objects-inl.h:3196
Map * elements_transition_map()
Definition: objects-inl.h:3502
void CopyKeysTo(FixedArray *storage, PropertyAttributes filter, SortMode sort_mode)
static Object * GetObjectFromEntryAddress(Address location_of_address)
Definition: objects-inl.h:3391
void ReportFailedAccessCheck(JSObject *receiver, v8::AccessType type)
Definition: isolate.cc:747
MUST_USE_RESULT MaybeObject * GetElementWithHandler(Object *receiver, uint32_t index)
Definition: objects.cc:252
uint64_t double_to_uint64(double d)
Definition: double.h:37
void AddSurrogatePairNoIndex(uc32 c)
Definition: objects.cc:7244
MaybeObject * AsObject()
Definition: objects.cc:10871
bool IsMatch(Object *string)
Definition: objects.cc:11037
bool HasRealNamedProperty(String *key)
Definition: objects.cc:10294
MUST_USE_RESULT MaybeObject * ConvertDescriptorToFieldAndMapTransition(String *name, Object *new_value, PropertyAttributes attributes)
Definition: objects.cc:1802
MUST_USE_RESULT MaybeObject * CopyInsert(Descriptor *descriptor, TransitionFlag transition_flag)
Definition: objects.cc:5838
SequentialSymbolKey(Vector< const Char > string, uint32_t seed)
Definition: objects.cc:10887
MUST_USE_RESULT MaybeObject * Update(String *name, Code *code)
Definition: objects.cc:5231
void CopyTo(int pos, FixedArray *dest, int dest_pos, int len)
Definition: objects.cc:5734
MUST_USE_RESULT MaybeObject * GetPropertyWithDefinedGetter(Object *receiver, JSReceiver *getter)
Definition: objects.cc:280
MUST_USE_RESULT MaybeObject * SetPropertyWithFailedAccessCheck(LookupResult *result, String *name, Object *value, bool check_prototype, StrictModeFlag strict_mode)
Definition: objects.cc:2444
static MUST_USE_RESULT MaybeObject * Allocate(int at_least_space_for, PretenureFlag pretenure=NOT_TENURED)
value format" "after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false, "print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false, "print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false, "report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true, "garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true, "flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true, "use incremental marking") DEFINE_bool(incremental_marking_steps, true, "do incremental marking steps") DEFINE_bool(trace_incremental_marking, false, "trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true, "Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false, "Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true, "use inline caching") DEFINE_bool(native_code_counters, false, "generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false, "Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true, "Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false, "Never perform compaction on full GC-testing only") DEFINE_bool(compact_code_space, true, "Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true, "Flush inline caches prior to mark compact collection and" "flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0, "Default seed for initializing random generator" "(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true, "allows verbose printing") DEFINE_bool(allow_natives_syntax, false, "allow natives syntax") DEFINE_bool(trace_sim, false, "Trace simulator execution") DEFINE_bool(check_icache, false, "Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8, "Stack alingment in bytes in simulator(4 or 8, 8 is default)") DEFINE_bool(trace_exception, false, "print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false, "preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true, "randomize hashes to avoid predictable hash collisions" "(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0, "Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false, "activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true, "generate optimized regexp code") DEFINE_bool(testing_bool_flag, true, "testing_bool_flag") DEFINE_int(testing_int_flag, 13, "testing_int_flag") DEFINE_float(testing_float_flag, 2.5, "float-flag") DEFINE_string(testing_string_flag, "Hello, world!", "string-flag") DEFINE_int(testing_prng_seed, 42, "Seed used for threading test randomness") DEFINE_string(testing_serialization_file, "/tmp/serdes", "file in which to serialize heap") DEFINE_bool(help, false, "Print usage message, including flags, on console") DEFINE_bool(dump_counters, false, "Dump counters on exit") DEFINE_string(map_counters, "", "Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT, "Pass all remaining arguments to the script.Alias for\"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#43"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2#define FLAG_MODE_DEFINE_DEFAULTS#1"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flag-definitions.h"1#define FLAG_FULL(ftype, ctype, nam, def, cmt)#define FLAG_READONLY(ftype, ctype, nam, def, cmt)#define DEFINE_implication(whenflag, thenflag)#define DEFINE_bool(nam, def, cmt)#define DEFINE_int(nam, def, cmt)#define DEFINE_float(nam, def, cmt)#define DEFINE_string(nam, def, cmt)#define DEFINE_args(nam, def, cmt)#define FLAG DEFINE_bool(use_strict, false,"enforce strict mode") DEFINE_bool(es5_readonly, false,"activate correct semantics for inheriting readonliness") DEFINE_bool(es52_globals, false,"activate new semantics for global var declarations") DEFINE_bool(harmony_typeof, false,"enable harmony semantics for typeof") DEFINE_bool(harmony_scoping, false,"enable harmony block scoping") DEFINE_bool(harmony_modules, false,"enable harmony modules (implies block scoping)") DEFINE_bool(harmony_proxies, false,"enable harmony proxies") DEFINE_bool(harmony_collections, false,"enable harmony collections (sets, maps, and weak maps)") DEFINE_bool(harmony, false,"enable all harmony features (except typeof)") DEFINE_implication(harmony, harmony_scoping) DEFINE_implication(harmony, harmony_modules) DEFINE_implication(harmony, harmony_proxies) DEFINE_implication(harmony, harmony_collections) DEFINE_implication(harmony_modules, harmony_scoping) DEFINE_bool(packed_arrays, false,"optimizes arrays that have no holes") DEFINE_bool(smi_only_arrays, true,"tracks arrays with only smi values") DEFINE_bool(clever_optimizations, true,"Optimize object size, Array shift, DOM strings and string +") DEFINE_bool(unbox_double_arrays, true,"automatically unbox arrays of doubles") DEFINE_bool(string_slices, true,"use string slices") DEFINE_bool(crankshaft, true,"use crankshaft") DEFINE_string(hydrogen_filter,"","optimization filter") DEFINE_bool(use_range, true,"use hydrogen range analysis") DEFINE_bool(eliminate_dead_phis, true,"eliminate dead phis") DEFINE_bool(use_gvn, true,"use hydrogen global value numbering") DEFINE_bool(use_canonicalizing, true,"use hydrogen instruction canonicalizing") DEFINE_bool(use_inlining, true,"use function inlining") DEFINE_int(max_inlined_source_size, 600,"maximum source size in bytes considered for a single inlining") DEFINE_int(max_inlined_nodes, 196,"maximum number of AST nodes considered for a single inlining") DEFINE_int(max_inlined_nodes_cumulative, 196,"maximum cumulative number of AST nodes considered for inlining") DEFINE_bool(loop_invariant_code_motion, true,"loop invariant code motion") DEFINE_bool(collect_megamorphic_maps_from_stub_cache, true,"crankshaft harvests type feedback from stub cache") DEFINE_bool(hydrogen_stats, false,"print statistics for hydrogen") DEFINE_bool(trace_hydrogen, false,"trace generated hydrogen to file") DEFINE_string(trace_phase,"Z","trace generated IR for specified phases") DEFINE_bool(trace_inlining, false,"trace inlining decisions") DEFINE_bool(trace_alloc, false,"trace register allocator") DEFINE_bool(trace_all_uses, false,"trace all use positions") DEFINE_bool(trace_range, false,"trace range analysis") DEFINE_bool(trace_gvn, false,"trace global value numbering") DEFINE_bool(trace_representation, false,"trace representation types") DEFINE_bool(stress_pointer_maps, false,"pointer map for every instruction") DEFINE_bool(stress_environments, false,"environment for every instruction") DEFINE_int(deopt_every_n_times, 0,"deoptimize every n times a deopt point is passed") DEFINE_bool(trap_on_deopt, false,"put a break point before deoptimizing") DEFINE_bool(deoptimize_uncommon_cases, true,"deoptimize uncommon cases") DEFINE_bool(polymorphic_inlining, true,"polymorphic inlining") DEFINE_bool(use_osr, true,"use on-stack replacement") DEFINE_bool(array_bounds_checks_elimination, false,"perform array bounds checks elimination") DEFINE_bool(array_index_dehoisting, false,"perform array index dehoisting") DEFINE_bool(trace_osr, false,"trace on-stack replacement") DEFINE_int(stress_runs, 0,"number of stress runs") DEFINE_bool(optimize_closures, true,"optimize closures") DEFINE_bool(inline_construct, true,"inline constructor calls") DEFINE_bool(inline_arguments, true,"inline functions with arguments object") DEFINE_int(loop_weight, 1,"loop weight for representation inference") DEFINE_bool(optimize_for_in, true,"optimize functions containing for-in loops") DEFINE_bool(experimental_profiler, true,"enable all profiler experiments") DEFINE_bool(watch_ic_patching, false,"profiler considers IC stability") DEFINE_int(frame_count, 1,"number of stack frames inspected by the profiler") DEFINE_bool(self_optimization, false,"primitive functions trigger their own optimization") DEFINE_bool(direct_self_opt, false,"call recompile stub directly when self-optimizing") DEFINE_bool(retry_self_opt, false,"re-try self-optimization if it failed") DEFINE_bool(count_based_interrupts, false,"trigger profiler ticks based on counting instead of timing") DEFINE_bool(interrupt_at_exit, false,"insert an interrupt check at function exit") DEFINE_bool(weighted_back_edges, false,"weight back edges by jump distance for interrupt triggering") DEFINE_int(interrupt_budget, 5900,"execution budget before interrupt is triggered") DEFINE_int(type_info_threshold, 15,"percentage of ICs that must have type info to allow optimization") DEFINE_int(self_opt_count, 130,"call count before self-optimization") DEFINE_implication(experimental_profiler, watch_ic_patching) DEFINE_implication(experimental_profiler, self_optimization) DEFINE_implication(experimental_profiler, retry_self_opt) DEFINE_implication(experimental_profiler, count_based_interrupts) DEFINE_implication(experimental_profiler, interrupt_at_exit) DEFINE_implication(experimental_profiler, weighted_back_edges) DEFINE_bool(trace_opt_verbose, false,"extra verbose compilation tracing") DEFINE_implication(trace_opt_verbose, trace_opt) DEFINE_bool(debug_code, false,"generate extra code (assertions) for debugging") DEFINE_bool(code_comments, false,"emit comments in code disassembly") DEFINE_bool(enable_sse2, true,"enable use of SSE2 instructions if available") DEFINE_bool(enable_sse3, true,"enable use of SSE3 instructions if available") DEFINE_bool(enable_sse4_1, true,"enable use of SSE4.1 instructions if available") DEFINE_bool(enable_cmov, true,"enable use of CMOV instruction if available") DEFINE_bool(enable_rdtsc, true,"enable use of RDTSC instruction if available") DEFINE_bool(enable_sahf, true,"enable use of SAHF instruction if available (X64 only)") DEFINE_bool(enable_vfp3, true,"enable use of VFP3 instructions if available - this implies ""enabling ARMv7 instructions (ARM only)") DEFINE_bool(enable_armv7, true,"enable use of ARMv7 instructions if available (ARM only)") DEFINE_bool(enable_fpu, true,"enable use of MIPS FPU instructions if available (MIPS only)") DEFINE_string(expose_natives_as, NULL,"expose natives in global object") DEFINE_string(expose_debug_as, NULL,"expose debug in global object") DEFINE_bool(expose_gc, false,"expose gc extension") DEFINE_bool(expose_externalize_string, false,"expose externalize string extension") DEFINE_int(stack_trace_limit, 10,"number of stack frames to capture") DEFINE_bool(builtins_in_stack_traces, false,"show built-in functions in stack traces") DEFINE_bool(disable_native_files, false,"disable builtin natives files") DEFINE_bool(inline_new, true,"use fast inline allocation") DEFINE_bool(stack_trace_on_abort, true,"print a stack trace if an assertion failure occurs") DEFINE_bool(trace, false,"trace function calls") DEFINE_bool(mask_constants_with_cookie, true,"use random jit cookie to mask large constants") DEFINE_bool(lazy, true,"use lazy compilation") DEFINE_bool(trace_opt, false,"trace lazy optimization") DEFINE_bool(trace_opt_stats, false,"trace lazy optimization statistics") DEFINE_bool(opt, true,"use adaptive optimizations") DEFINE_bool(always_opt, false,"always try to optimize functions") DEFINE_bool(prepare_always_opt, false,"prepare for turning on always opt") DEFINE_bool(trace_deopt, false,"trace deoptimization") DEFINE_int(min_preparse_length, 1024,"minimum length for automatic enable preparsing") DEFINE_bool(always_full_compiler, false,"try to use the dedicated run-once backend for all code") DEFINE_bool(trace_bailout, false,"print reasons for falling back to using the classic V8 backend") DEFINE_bool(compilation_cache, true,"enable compilation cache") DEFINE_bool(cache_prototype_transitions, true,"cache prototype transitions") DEFINE_bool(trace_debug_json, false,"trace debugging JSON request/response") DEFINE_bool(debugger_auto_break, true,"automatically set the debug break flag when debugger commands are ""in the queue") DEFINE_bool(enable_liveedit, true,"enable liveedit experimental feature") DEFINE_bool(break_on_abort, true,"always cause a debug break before aborting") DEFINE_int(stack_size, kPointerSize *123,"default size of stack region v8 is allowed to use (in kBytes)") DEFINE_int(max_stack_trace_source_length, 300,"maximum length of function source code printed in a stack trace.") DEFINE_bool(always_inline_smi_code, false,"always inline smi code in non-opt code") DEFINE_int(max_new_space_size, 0,"max size of the new generation (in kBytes)") DEFINE_int(max_old_space_size, 0,"max size of the old generation (in Mbytes)") DEFINE_int(max_executable_size, 0,"max size of executable memory (in Mbytes)") DEFINE_bool(gc_global, false,"always perform global GCs") DEFINE_int(gc_interval,-1,"garbage collect after <n> allocations") DEFINE_bool(trace_gc, false,"print one trace line following each garbage collection") DEFINE_bool(trace_gc_nvp, false,"print one detailed trace line in name=value format ""after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false,"print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false,"print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false,"report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true,"garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true,"flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true,"use incremental marking") DEFINE_bool(incremental_marking_steps, true,"do incremental marking steps") DEFINE_bool(trace_incremental_marking, false,"trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true,"Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false,"Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true,"use inline caching") DEFINE_bool(native_code_counters, false,"generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false,"Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true,"Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false,"Never perform compaction on full GC - testing only") DEFINE_bool(compact_code_space, true,"Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true,"Flush inline caches prior to mark compact collection and ""flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0,"Default seed for initializing random generator ""(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true,"allows verbose printing") DEFINE_bool(allow_natives_syntax, false,"allow natives syntax") DEFINE_bool(trace_sim, false,"Trace simulator execution") DEFINE_bool(check_icache, false,"Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0,"Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8,"Stack alingment in bytes in simulator (4 or 8, 8 is default)") DEFINE_bool(trace_exception, false,"print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false,"preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true,"randomize hashes to avoid predictable hash collisions ""(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0,"Fixed seed to use to hash property keys (0 means random)""(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false,"activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true,"generate optimized regexp code") DEFINE_bool(testing_bool_flag, true,"testing_bool_flag") DEFINE_int(testing_int_flag, 13,"testing_int_flag") DEFINE_float(testing_float_flag, 2.5,"float-flag") DEFINE_string(testing_string_flag,"Hello, world!","string-flag") DEFINE_int(testing_prng_seed, 42,"Seed used for threading test randomness") DEFINE_string(testing_serialization_file,"/tmp/serdes","file in which to serialize heap") DEFINE_bool(help, false,"Print usage message, including flags, on console") DEFINE_bool(dump_counters, false,"Dump counters on exit") DEFINE_string(map_counters,"","Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT,"Pass all remaining arguments to the script. Alias for \"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#47"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2 namespace{struct Flag{enum FlagType{TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS} name
Definition: flags.cc:1349
static HeapObject * cast(Object *obj)
MUST_USE_RESULT MaybeObject * Rehash(HashTable *new_table, Key key)
Definition: objects.cc:11173
MUST_USE_RESULT MaybeObject * SetInstancePrototype(Object *value)
Definition: objects.cc:7542
static Handle< T > cast(Handle< S > that)
Definition: handles.h:81
MUST_USE_RESULT MaybeObject * SetPrototype(Object *value)
Definition: objects.cc:7577
static bool EncodeNonAsciiCharacter(uchar c, byte *buffer, unsigned capacity, unsigned &offset)
Definition: unicode-inl.h:168
bool MayNamedAccess(JSObject *receiver, Object *key, v8::AccessType type)
Definition: isolate.cc:801
static const int kMaxHashCalcLength
Definition: objects.h:7170
void Sort(const WhitenessWitness &)
Definition: objects.cc:6020
IntrusiveMapTransitionIterator(DescriptorArray *descriptor_array)
Definition: objects.cc:4992
static PropertyType ExtractTypeFromFlags(Flags flags)
Definition: objects-inl.h:3359
MUST_USE_RESULT MaybeObject * AllocateCodeCache()
Definition: heap.cc:2047
void set_pre_allocated_property_fields(int value)
Definition: objects-inl.h:2856
const unibrow::byte * ExternalAsciiStringReadBlock(unsigned *remaining, unsigned *offset, unsigned chars)
Definition: objects.cc:6391
static CodeCacheHashTable * cast(Object *obj)
static const int kProtoTransitionElementsPerEntry
Definition: objects.h:4802
static AccessorPair * cast(Object *obj)
MUST_USE_RESULT MaybeObject * AddKeysFromJSArray(JSArray *array)
Definition: objects.cc:5675
static void IterateBody(HeapObject *obj, int object_size, ObjectVisitor *v)
static Failure * OutOfMemoryException()
Definition: objects-inl.h:1021
JSFunction * GetConstantFunction(int descriptor_number)
Definition: objects-inl.h:2019
PropertyAttributes property_attributes()
Definition: objects-inl.h:4840
bool IsAsciiRepresentation()
Definition: objects-inl.h:289
TwoCharHashTableKey(uint32_t c1, uint32_t c2, uint32_t seed)
Definition: objects.cc:11847
static ExternalTwoByteString * cast(Object *obj)
bool IsMatch(Object *obj)
Definition: objects.cc:10817
void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6404
TraversableMap * GetAndResetParent()
Definition: objects.cc:5162
int GetEnumElementKeys(FixedArray *storage)
Definition: objects.cc:10684
int32_t uc32
Definition: globals.h:274
MUST_USE_RESULT MaybeObject * GetPropertyWithFailedAccessCheck(Object *receiver, LookupResult *result, String *name, PropertyAttributes *attributes)
Definition: objects.cc:305
SeededNumberDictionary * element_dictionary()
Definition: objects-inl.h:4632
static uint32_t StringHash(Object *obj)
Definition: objects.cc:11066
Vector< const char > ToAsciiVector()
Definition: objects.h:6918
static Map * cast(Object *obj)
MUST_USE_RESULT MaybeObject * AddNumberEntry(uint32_t key, Object *value, PropertyDetails details)
Definition: objects.cc:12369
Object * ToBoolean()
Definition: objects.cc:107
MUST_USE_RESULT MaybeObject * RemoveTransitions(SharedMode shared_mode)
Definition: objects.cc:5935
MUST_USE_RESULT MaybeObject * ConvertDescriptorToField(String *name, Object *new_value, PropertyAttributes attributes)
Definition: objects.cc:1839
MUST_USE_RESULT MaybeObject * GetPropertyWithReceiver(Object *receiver, String *key, PropertyAttributes *attributes)
Definition: objects.cc:151
static ByteArray * cast(Object *obj)
int BinarySearch(String *name, int low, int high)
Definition: objects.cc:6026
static uint32_t ComputeHashField(unibrow::CharacterStream *buffer, int length, uint32_t seed)
Definition: objects.cc:7265
T & at(int i) const
Definition: list.h:85
MUST_USE_RESULT MaybeObject * SetElementWithCallbackSetterInPrototypes(uint32_t index, Object *value, bool *found, StrictModeFlag strict_mode)
Definition: objects.cc:2070
Flag flags[]
Definition: flags.cc:1467
static const int kNoNumber
Definition: ast.h:197
MUST_USE_RESULT MaybeObject * AsObject()
Definition: objects.cc:5437
Builtins * builtins()
Definition: isolate.h:909
static const int kInstanceDescriptorsOrBitField3Offset
Definition: objects.h:4964
void ConsStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6705
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:636
void Set(int descriptor_number, Descriptor *desc, const WhitenessWitness &)
Definition: objects-inl.h:2079
MUST_USE_RESULT MaybeObject * Uint32ToString(uint32_t value, bool check_number_string_cache=true)
Definition: heap.cc:2929
bool SameValue(Object *other)
Definition: objects.cc:764
void Relocate(intptr_t delta)
Definition: objects.cc:8112
static Failure * Exception()
Definition: objects-inl.h:1016
MUST_USE_RESULT MaybeObject * PutRegExp(String *src, JSRegExp::Flags flags, FixedArray *value)
Definition: objects.cc:12075
#define REGISTER(N, C)
const int kMaxInt
Definition: globals.h:224
static Foreign * cast(Object *obj)
static bool enabled()
Definition: serialize.h:480
MUST_USE_RESULT MaybeObject * GetElementsTransitionMapSlow(ElementsKind elements_kind)
Definition: objects.cc:2328
MUST_USE_RESULT MaybeObject * ToObject()
Definition: objects.cc:85
MUST_USE_RESULT MaybeObject * PrepareElementsForSort(uint32_t limit)
Definition: objects.cc:11489
void set_map(Map *value)
Definition: objects-inl.h:1135
Map * SymbolMapForString(String *str)
Definition: heap.cc:4383
bool MakeExternal(v8::String::ExternalStringResource *resource)
Definition: objects.cc:909
int GetLocalElementKeys(FixedArray *storage, PropertyAttributes filter)
Definition: objects.cc:10548
Object * Lookup(String *src)
Definition: objects.cc:11998
int SourceStatementPosition(Address pc)
Definition: objects.cc:8197
Map * LookupElementsTransitionMap(ElementsKind elements_kind)
Definition: objects.cc:2254
void PrintElementsTransition(FILE *file, ElementsKind from_kind, FixedArrayBase *from_elements, ElementsKind to_kind, FixedArrayBase *to_elements)
Definition: objects.cc:1152
static const int kSize
Definition: objects.h:7518
static AliasedArgumentsEntry * cast(Object *obj)
bool IsTwoByteEqualTo(Vector< const uc16 > str)
Definition: objects.cc:7127
uint16_t SlicedStringGet(int index)
Definition: objects.cc:6793
bool Contains(Object *key)
Definition: objects.cc:12702
Context * global_context()
Definition: contexts.cc:58
static Handle< Object > TransitionElementsKind(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:9848
Handle< Object > Lookup(MapHandleList *maps, Code::Flags flags)
Definition: objects.cc:5541
Object * HeapNumberToBoolean()
Definition: objects.cc:1420
List< Handle< Map > > MapHandleList
Definition: list.h:193
#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)
MUST_USE_RESULT MaybeObject * SetElement(uint32_t index, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode, bool check_prototype)
Definition: objects.cc:9636
static Handle< Object > SetOwnElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictModeFlag strict_mode)
Definition: objects.cc:9651
MUST_USE_RESULT MaybeObject * PreventExtensions()
Definition: objects.cc:4044
Map * GetPrototypeTransition(Object *prototype)
Definition: objects.cc:8733
void set_profiler_ticks(int ticks)
Definition: objects-inl.h:3164
static ExternalUnsignedShortArray * cast(Object *obj)
MUST_USE_RESULT MaybeObject * UnionOfKeys(FixedArray *other)
Definition: objects.cc:5693
struct v8::internal::IeeeDoubleBigEndianArchType::@29 bits
static Script * cast(Object *obj)
MUST_USE_RESULT MaybeObject * PutEval(String *src, Context *context, SharedFunctionInfo *value, int scope_position)
Definition: objects.cc:12046
unsigned short uint16_t
Definition: unicode.cc:46
void set_optimizable(bool value)
Definition: objects-inl.h:3094
void LookupCallback(String *name, LookupResult *result)
Definition: objects.cc:4226
int SourcePosition(Address pc)
Definition: objects.cc:8165
void SetNullValueUnchecked(int descriptor_number, Heap *heap)
Definition: objects-inl.h:1990
MUST_USE_RESULT MaybeObject * EnsureCapacity(int n, Key key)
Definition: objects.cc:11207
#define VISITOR_SYNCHRONIZATION_TAGS_LIST(V)
Definition: objects.h:8639
static Dictionary< Shape, Key > * cast(Object *obj)
Definition: objects.h:3034
#define CALL_HEAP_FUNCTION_VOID(ISOLATE, FUNCTION_CALL)
Definition: heap-inl.h:556
MUST_USE_RESULT MaybeObject * EnsureCapacity(int n, Key key)
Definition: objects.cc:12242
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11715
static Context * cast(Object *context)
Definition: contexts.h:207
static MUST_USE_RESULT MaybeObject * Allocate(int deopt_entry_count, PretenureFlag pretenure)
Definition: objects.cc:6084
Object * SlowReverseLookup(Object *value)
Definition: objects.cc:4818
MUST_USE_RESULT MaybeObject * LookupSymbol(Vector< const char > str)
Definition: heap.cc:5321
static const int kSourceIndex
Definition: objects.h:6437
PropertyAttributes GetPropertyAttributePostInterceptor(JSObject *receiver, String *name, bool continue_search)
Definition: objects.cc:3012
static SharedFunctionInfo * cast(Object *obj)
const uint32_t kStringRepresentationMask
Definition: objects.h:455
PropertyType type()
Definition: objects-inl.h:3043
int SizeFromMap(Map *map)
Definition: objects-inl.h:2809
#define CHECK(condition)
Definition: checks.h:56
bool HasElementWithInterceptor(JSReceiver *receiver, uint32_t index)
Definition: objects.cc:8892
void RemoveFromCodeCache(String *name, Code *code, int index)
Definition: objects.cc:4980
static const int kShortSize
Definition: objects.h:7516
Handle< Value >(* IndexedPropertySetter)(uint32_t index, Local< Value > value, const AccessorInfo &info)
Definition: v8.h:2071
MaybeObject * AsObject()
Definition: objects.cc:10941
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:6246
bool ContainsTransition(int entry)
Definition: objects.cc:11148
Handle< String > NumberToString(Handle< Object > number)
Definition: factory.cc:1144
bool ReferencesObject(Object *obj)
Definition: objects.cc:3931
void ReplaceCode(Code *code)
Definition: objects-inl.h:4090
const uc16 * GetTwoByteData()
Definition: objects.cc:6220
void CopyEnumKeysTo(FixedArray *storage, FixedArray *sort_array)
Definition: objects.cc:12497
void set_map_and_elements(Map *map, FixedArrayBase *value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
Definition: objects-inl.h:1352
Factory * factory()
Definition: isolate.h:977
bool IsFastElementsKind(ElementsKind kind)
static ExternalAsciiString * cast(Object *obj)
MUST_USE_RESULT MaybeObject * EnsureWritableFastElements()
Definition: objects-inl.h:4608
PropertyAttributes
void set_the_hole(int index)
Definition: objects-inl.h:1838
static const int kInvalidStamp
Definition: date.h:63
MUST_USE_RESULT MaybeObject * DeletePropertyWithHandler(String *name, DeleteMode mode)
Definition: objects.cc:2640
static Code * cast(Object *obj)
Handle< String > LookupAsciiSymbol(Vector< const char > str)
Definition: factory.cc:174
bool IsMatch(Object *string)
Definition: objects.cc:10697
virtual const uint16_t * data() const =0
static Handle< Object > SetHiddenProperty(Handle< JSObject > obj, Handle< String > key, Handle< Object > value)
Definition: objects.cc:3551
MUST_USE_RESULT MaybeObject * AllocateInternalSymbol(unibrow::CharacterStream *buffer, int chars, uint32_t hash_field)
Definition: heap.cc:4407
static uint32_t StringSharedHashHelper(String *source, SharedFunctionInfo *shared, LanguageMode language_mode, int scope_position)
Definition: objects.cc:10746
MUST_USE_RESULT MaybeObject * LookupSubStringAsciiSymbol(Handle< SeqAsciiString > str, int from, int length, Object **s)
Definition: objects.cc:11948
bool HasElementWithReceiver(JSReceiver *receiver, uint32_t index)
Definition: objects.cc:9058
int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind)
bool AsArrayIndex(uint32_t *index)
Definition: objects-inl.h:4748
Object * GetValue(int descriptor_number)
Definition: objects-inl.h:1984
static Object ** RawField(HeapObject *obj, int offset)
Definition: objects-inl.h:963
const int kIntSize
Definition: globals.h:231
Object * GetNormalizedProperty(LookupResult *result)
Definition: objects.cc:428
MUST_USE_RESULT MaybeObject * AllocateHeapNumber(double value, PretenureFlag pretenure)
Definition: heap.cc:2407
static Smi * cast(Object *object)
static const char * AllocationIndexToString(int index)
static void IterateBody(HeapObject *obj, ObjectVisitor *v)
Definition: objects-inl.h:5143
unsigned int seed
Definition: test-strings.cc:17
void PrintOn(FILE *out)
Definition: objects.cc:7300
void ClearCodeCache(Heap *heap)
Definition: objects-inl.h:4963
MUST_USE_RESULT MaybeObject * SetIdentityHash(Object *hash, CreationFlag flag)
Definition: objects.cc:3483
bool Equals(String *other)
Definition: objects-inl.h:2275
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:3148
void Lookup(String *name, LookupResult *result)
Definition: objects.cc:132
void set_used_for_prototype(bool value)
Definition: objects-inl.h:2985
Vector< const char > string_
Definition: objects.cc:10877
MaybeObject *(* setter)(JSObject *object, Object *value, void *data)
Definition: v8globals.h:358
Handle< Object > CallTrap(const char *name, Handle< Object > derived_trap, int argc, Handle< Object > args[])
Definition: objects.cc:2763
static ExternalShortArray * cast(Object *obj)
MaybeObject *(* getter)(Object *object, void *data)
Definition: v8globals.h:357
JSGlobalPropertyCell * GetPropertyCell(LookupResult *result)
Definition: objects.cc:11790
static MarkBit MarkBitFrom(Address addr)
MUST_USE_RESULT MaybeObject * AddNumberEntry(uint32_t key, Object *value)
Definition: objects.cc:12378
void Add(Vector< const char > format, Vector< FmtElm > elms)
Handle< Value >(* IndexedPropertyGetter)(uint32_t index, const AccessorInfo &info)
Definition: v8.h:2063
void IterateBody(InstanceType type, int object_size, ObjectVisitor *v)
Definition: objects.cc:1313
uint8_t byte
Definition: globals.h:171
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:6161
MUST_USE_RESULT MaybeObject * SetPropertyWithCallback(Object *structure, String *name, Object *value, JSObject *holder, StrictModeFlag strict_mode)
Definition: objects.cc:1966
Object * ValueAt(int entry)
Definition: objects.h:3039
Object * InObjectPropertyAtPut(int index, Object *value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
Definition: objects-inl.h:1566
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11749
bool IsMatch(Object *symbols)
Definition: objects.cc:12116
bool LookupSymbolIfExists(String *str, String **symbol)
Definition: objects.cc:11904
const uint16_t * SeqTwoByteStringGetData(unsigned start)
Definition: objects.cc:6268
static const int kMaxCachedPrototypeTransitions
Definition: objects.h:4941
MUST_USE_RESULT MaybeObject * LookupTwoByteSymbol(Vector< const uc16 > str, Object **s)
Definition: objects.cc:11957
void set_null(int index)
Definition: objects-inl.h:1826
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset this_property_assignments
Definition: objects-inl.h:3674
UnicodeCache * unicode_cache()
Definition: isolate.h:855
MUST_USE_RESULT MaybeObject * GetIdentityHash(CreationFlag flag)
Definition: objects.cc:3518
void RemoveByIndex(Object *name, Code *code, int index)
Definition: objects.cc:5379
static uchar Length(uchar chr, int previous)
Definition: unicode-inl.h:123
static const uint32_t kMaxGap
Definition: objects.h:2093
String * GetKey(int descriptor_number)
Definition: objects-inl.h:1970
TwoByteSymbolKey(Vector< const uc16 > str, uint32_t seed)
Definition: objects.cc:11017
MUST_USE_RESULT MaybeObject * GetIdentityHash(CreationFlag flag)
Definition: objects-inl.h:4795
bool IsMatch(Object *other)
Definition: objects.cc:10729
static void DeoptimizeGlobalObject(JSObject *object)
Definition: deoptimizer.cc:261
virtual size_t length() const =0
void Iterate(ObjectVisitor *v)
Definition: objects.cc:1304
uint32_t HashForObject(Object *other)
Definition: objects.cc:10921
#define UNREACHABLE()
Definition: checks.h:50
MUST_USE_RESULT MaybeObject * AddFastPropertyUsingMap(Map *new_map, String *name, Object *value)
Definition: objects.cc:1489
Handle< Value >(* NamedPropertyGetter)(Local< String > property, const AccessorInfo &info)
Definition: v8.h:2023
virtual MUST_USE_RESULT MaybeObject * AddElementsToFixedArray(Object *receiver, JSObject *holder, FixedArray *to, FixedArrayBase *from=NULL)=0
MUST_USE_RESULT MaybeObject * SetFastElement(uint32_t index, Object *value, StrictModeFlag strict_mode, bool check_prototype)
Definition: objects.cc:9273
static void Update(Handle< PolymorphicCodeCache > cache, MapHandleList *maps, Code::Flags flags, Handle< Code > code)
Definition: objects.cc:5504
T * start() const
Definition: utils.h:389
MUST_USE_RESULT MaybeObject * AllocateUninitializedFixedDoubleArray(int length, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:4759
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:5559
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
static SeededNumberDictionary * cast(Object *obj)
Definition: objects.h:3207
virtual const char * NameOfCPURegister(int reg) const
bool MarkAsUndetectable()
Definition: objects.cc:7074
void LookupRealNamedPropertyInPrototypes(String *name, LookupResult *result)
Definition: objects.cc:2426
int NumberOfElementsFilterAttributes(PropertyAttributes filter)
Definition: objects.cc:12449
Object * SetInstanceClassName(String *name)
Definition: objects.cc:7630
MUST_USE_RESULT MaybeObject * AddConstantFunctionProperty(String *name, JSFunction *function, PropertyAttributes attributes)
Definition: objects.cc:1621
MUST_USE_RESULT MaybeObject * AddFastProperty(String *name, Object *value, PropertyAttributes attributes, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:1524
static Context * GlobalContextFromLiterals(FixedArray *literals)
Definition: objects.cc:7642
bool IsStringObjectWithCharacterAt(uint32_t index)
Definition: objects-inl.h:1656
#define MUST_USE_RESULT
Definition: globals.h:360
bool IsFastPackedElementsKind(ElementsKind kind)
MUST_USE_RESULT MaybeObject * Put(FixedArray *key, Map *value)
Definition: objects.cc:12153
virtual void Seek(unsigned)
Definition: unicode.cc:352
void set_undefined(int index)
Definition: objects-inl.h:1812
MUST_USE_RESULT MaybeObject * GetLocalPropertyPostInterceptor(JSReceiver *receiver, String *name, PropertyAttributes *attributes)
Definition: objects.cc:10240
static SlicedString * cast(Object *obj)
static ExternalIntArray * cast(Object *obj)
static const int kProtoTransitionMapOffset
Definition: objects.h:4804
SymbolKey(String *string)
Definition: objects.cc:11034
MUST_USE_RESULT MaybeObject * SetElementsLength(Object *length)
Definition: objects.cc:8726
void set_expected_nof_properties(int value)
void SetNumberOfProtoTransitions(int value)
Definition: objects.h:4813
void SetNumberOfElements(int nof)
Definition: objects.h:2872
static const int kLiteralGlobalContextIndex
Definition: objects.h:5994
MUST_USE_RESULT MaybeObject * SetElementWithHandler(JSReceiver *receiver, uint32_t index, Object *value, StrictModeFlag strict_mode)
Definition: objects.cc:261
Handle< Integer >(* NamedPropertyQuery)(Local< String > property, const AccessorInfo &info)
Definition: v8.h:2040
MUST_USE_RESULT MaybeObject * SetFastDoubleElement(uint32_t index, Object *value, StrictModeFlag strict_mode, bool check_prototype=true)
Definition: objects.cc:9533
static uint32_t MapsHashHelper(MapHandleList *maps, int code_flags)
Definition: objects.cc:5590
void IteratePointers(ObjectVisitor *v, int start, int end)
Definition: objects-inl.h:1179
MUST_USE_RESULT MaybeObject * AddEntry(Key key, Object *value, PropertyDetails details, uint32_t hash)
Definition: objects.cc:12323
static bool IsValidElementsTransition(ElementsKind from_kind, ElementsKind to_kind)
Definition: objects.cc:9924
static const uchar kMaxNonSurrogateCharCode
Definition: unicode.h:133
void SetIdentityHash(Handle< JSObject > object, Object *hash)
Definition: factory.cc:1091
void GetLocalPropertyNames(FixedArray *storage, int index)
Definition: objects.cc:10513
static Failure * cast(MaybeObject *object)
Definition: objects-inl.h:485
#define CALL_HEAP_FUNCTION(ISOLATE, FUNCTION_CALL, TYPE)
Definition: heap-inl.h:549
void ResetForNewContext(int new_ic_age)
Definition: objects.cc:7974
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11770
bool ToArrayIndex(uint32_t *index)
Definition: objects-inl.h:1637
ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number)
void SetElementsCapacityAndLength(Handle< JSArray > array, int capacity, int length)
Definition: factory.cc:1031
ElementsKind GetElementsKind()
Definition: objects-inl.h:4503
byte * instruction_start()
Definition: objects-inl.h:4376
static Object * RawUninitializedSentinel(Heap *heap)
Definition: objects-inl.h:5062
static Handle< Map > GetElementsTransitionMap(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:2303
MUST_USE_RESULT MaybeObject * AllocateFixedArrayWithHoles(int length, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:4720
const int kPointerSize
Definition: globals.h:234
#define MAKE_STRUCT_CASE(NAME, Name, name)
static const int kMaxCachedArrayIndexLength
Definition: objects.h:7129
Object * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11636
MUST_USE_RESULT MaybeObject * DeleteElement(uint32_t index, DeleteMode mode)
Definition: objects.cc:3892
static const char *const kTags[kNumberOfSyncTags]
Definition: objects.h:8664
static const int kIsNotArrayIndexMask
Definition: objects.h:7117
uint32_t HashForObject(Key key, Object *object)
Definition: objects.h:2767
static const int kIsShared
Definition: objects.h:5034
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:6573
static const int kMaxInstanceSize
Definition: objects.h:2106
int GetFieldIndex(int descriptor_number)
Definition: objects-inl.h:2014
const int kHeapObjectTag
Definition: v8.h:3848
Handle< Integer >(* IndexedPropertyQuery)(uint32_t index, const AccessorInfo &info)
Definition: v8.h:2080
MUST_USE_RESULT MaybeObject * GenerateNewEnumerationIndices()
Definition: objects.cc:12184
MUST_USE_RESULT MaybeObject * PutPrototypeTransition(Object *prototype, Map *map)
Definition: objects.cc:8750
void LookupRealNamedProperty(String *name, LookupResult *result)
Definition: objects.cc:2418
static SeqAsciiString * cast(Object *obj)
void set_inobject_properties(int value)
Definition: objects-inl.h:2850
Handle< Object > GetSourceCode()
Definition: objects.cc:7675
void set_hash_field(uint32_t value)
Definition: objects-inl.h:2267
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11701
V8EXPORT int32_t Int32Value() const
Definition: api.cc:2654
void(* AccessorSetter)(Local< String > property, Local< Value > value, const AccessorInfo &info)
Definition: v8.h:1428
static ExternalUnsignedByteArray * cast(Object *obj)
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
static const int kProtoTransitionNumberOfEntriesOffset
Definition: objects.h:4800
static void TransformToFastProperties(Handle< JSObject > object, int unused_property_fields)
Definition: objects.cc:3352
static int TimeInDay(int64_t time_ms, int days)
Definition: date.h:85
uint32_t HashForObject(Object *other)
Definition: objects.cc:10991
static unsigned decode(uint32_t value)
Definition: utils.h:272
void SetCapacity(int capacity)
Definition: objects.h:2882
MUST_USE_RESULT MaybeObject * set_initial_map_and_cache_transitions(Map *value)
Definition: objects-inl.h:4143
void SmiPrint()
Definition: objects.h:995
bool ShouldConvertToFastDoubleElements(bool *has_smi_only_elements)
Definition: objects.cc:10133
static Handle< Object > SetLocalPropertyIgnoreAttributes(Handle< JSObject > object, Handle< String > key, Handle< Object > value, PropertyAttributes attributes)
Definition: objects.cc:2924
const Register pc
Vector< const uc16 > ToUC16Vector()
Definition: objects.h:6924
uint32_t FindInsertionEntry(uint32_t hash)
Definition: objects.cc:11262
void LookupInDescriptors(JSObject *holder, String *name, LookupResult *result)
Definition: objects.cc:2180
SafepointEntry GetSafepointEntry(Address pc)
Definition: objects.cc:8217
int length() const
Definition: utils.h:383
static const int kPropertiesOffset
Definition: objects.h:2113
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:514
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:9663
MUST_USE_RESULT MaybeObject * CopyWithoutTransitions()
Definition: objects.cc:6066
static const char * State2String(State state)
Definition: full-codegen.h:104
static int GetOutputInfo(DeoptimizationOutputData *data, unsigned node_id, SharedFunctionInfo *shared)
Definition: deoptimizer.cc:486
int GetIndex(Object *name, Code *code)
Definition: objects.cc:5363
Object * FastPropertyAt(int index)
Definition: objects-inl.h:1521
static ExternalPixelArray * cast(Object *obj)
static const int kSize
Definition: objects.h:4972
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:3380
bool is_inline_cache_stub()
Definition: objects-inl.h:3306
CodeCacheHashTableKey(String *name, Code::Flags flags)
Definition: objects.cc:5404
bool IsFastSmiElementsKind(ElementsKind kind)
MUST_USE_RESULT MaybeObject * CopyNormalized(PropertyNormalizationMode mode, NormalizedMapSharingMode sharing)
Definition: objects.cc:4883
bool has_pending_exception()
Definition: isolate.h:554
MUST_USE_RESULT MaybeObject * SetFastElementsCapacityAndLength(int capacity, int length, SetFastElementsCapacitySmiMode smi_mode)
Definition: objects.cc:8584
Object * FastPropertyAtPut(int index, Object *value)
Definition: objects-inl.h:1534
void set_kind(byte kind)
Definition: objects-inl.h:1418
static ElementsAccessor * ForArray(FixedArrayBase *array)
Definition: elements.cc:1574
MUST_USE_RESULT MaybeObject * DeleteElementWithHandler(uint32_t index, DeleteMode mode)
Definition: objects.cc:2665
MUST_USE_RESULT MaybeObject * SetPropertyViaPrototypesWithHandler(JSReceiver *receiver, String *name, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode, bool *done)
Definition: objects.cc:2551
void Update(DescriptorArray *array, String *name, int result)
Definition: heap.h:2296
static int GetIdentityHash(Handle< JSObject > obj)
Definition: objects.cc:3491
static uint32_t NameFlagsHashHelper(String *name, Code::Flags flags)
Definition: objects.cc:5424
void CopyFrom(const CodeDesc &desc)
Definition: objects.cc:8120
bool HasRealNamedCallbackProperty(String *key)
Definition: objects.cc:10374
InterceptorInfo * GetNamedInterceptor()
Definition: objects.cc:10202
const unibrow::byte * ConsStringReadBlock(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6326
void SortPairs(FixedArray *numbers, uint32_t len)
Definition: objects.cc:10471
static const int kContainsCachedArrayIndexMask
Definition: objects.h:7154
WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation &)
Definition: objects-inl.h:1769
MUST_USE_RESULT MaybeObject * Shrink(Key key)
Definition: objects.cc:12272
int CompareChars(const lchar *lhs, const rchar *rhs, int chars)
Definition: utils.h:767
PropertyDetails GetDetails(int descriptor_number)
Definition: objects-inl.h:1996
int TenToThe(int exponent)
Definition: utils.h:794
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:11695
static bool ComputeArrayIndex(unibrow::CharacterStream *buffer, uint32_t *index, int length)
Definition: objects.cc:7173
TraversableMap * ChildIteratorNext()
Definition: objects.cc:5192
void SetNumberOfDeletedElements(int nod)
Definition: objects.h:2877
MUST_USE_RESULT MaybeObject * GetPropertyPostInterceptor(JSReceiver *receiver, String *name, PropertyAttributes *attributes)
Definition: objects.cc:10222
Failure * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:918
bool is_call_stub()
Definition: objects.h:4264
InlineCacheState ic_state()
Definition: objects-inl.h:3024
byte * relocation_start()
Definition: objects-inl.h:4402
Assembler * origin
Definition: v8globals.h:239
void set_construction_count(int value)
Definition: objects-inl.h:3792
double get_scalar(int index)
Definition: objects-inl.h:1721
Object * Lookup(Object *key)
Definition: objects.cc:12759
static uint32_t MakeArrayIndexHash(uint32_t value, int length)
Definition: objects.cc:7218
static MUST_USE_RESULT MaybeObject * Allocate(int at_least_space_for)
Handle< Map > FindTransitionedMap(MapHandleList *candidates)
Definition: objects.cc:2215
uint16_t ConsStringGet(int index)
Definition: objects.cc:6762
void Lookup(String *name, LookupResult *result)
Definition: objects.cc:4212
DescriptorLookupCache * descriptor_lookup_cache()
Definition: isolate.h:842
void set_map_no_write_barrier(Map *value)
Definition: objects-inl.h:1146
MUST_USE_RESULT MaybeObject * SetPropertyPostInterceptor(String *name, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: objects.cc:1762
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:144
bool LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String **symbol)
Definition: objects.cc:11918
MUST_USE_RESULT MaybeObject * Initialize(int capacity)
Definition: objects.cc:8704
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:81
int Weekday(int days)
Definition: date.h:92
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
Object * SlowReverseLookup(Object *value)
Definition: objects.cc:12542
#define DECLARE_TAG(ignore1, name, ignore2)
Definition: objects.cc:8048
static JSArray * cast(Object *obj)
PropertyAttributes GetPropertyAttributeWithReceiver(JSReceiver *receiver, String *name)
Definition: objects.cc:3084
void HeapSortPairs(FixedArray *content, FixedArray *numbers, int len)
Definition: objects.cc:10424
#define T(name, string, precedence)
Definition: token.cc:48
static Object * GetField(Object *date, Smi *index)
Definition: objects.cc:13076
static const int kProtoTransitionHeaderSize
Definition: objects.h:4799
Context * context()
Definition: isolate.h:518
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
static JSDate * cast(Object *obj)
Definition: objects-inl.h:4345
void SetNextEnumerationIndex(int index)
Definition: objects.h:3085
static ElementsAccessor * ForKind(ElementsKind elements_kind)
Definition: elements.h:134
bool IsThisPropertyAssignmentArgument(int index)
Definition: objects.cc:7777
bool IsMatch(Object *string)
Definition: objects.cc:11020
static SeqTwoByteString * cast(Object *obj)
int PropertyIndexFor(String *name)
Definition: objects.cc:4135
const unibrow::byte * SeqAsciiStringReadBlock(unsigned *remaining, unsigned *offset, unsigned chars)
Definition: objects.cc:6307
LocalElementType HasLocalElement(uint32_t index)
Definition: objects.cc:8949
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:4936
static const unibrow::byte * ReadBlock(String *input, unibrow::byte *util_buffer, unsigned capacity, unsigned *remaining, unsigned *offset)
Definition: objects.cc:6668
PropertyNormalizationMode
Definition: objects.h:152
static ExternalFloatArray * cast(Object *obj)
bool HasElementWithHandler(uint32_t index)
Definition: objects.cc:272
MUST_USE_RESULT MaybeObject * Put(String *name, Code *code)
Definition: objects.cc:5465
FlatContent GetFlatContent()
Definition: objects.cc:6119
void set(int index, double value)
Definition: objects-inl.h:1746
static const int kMaxShortPrintLength
Definition: objects.h:7173
static int SNPrintF(Vector< char > str, const char *format,...)
bool IsKey(Object *k)
Definition: objects.h:2820
MUST_USE_RESULT MaybeObject * NumberFromDouble(double value, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:2971
void PrintElementsKind(FILE *out, ElementsKind kind)
MUST_USE_RESULT MaybeObject * SetFastDoubleElementsCapacityAndLength(int capacity, int length)
Definition: objects.cc:8650
int NumberOfDescribedProperties(PropertyAttributes filter=NONE)
Definition: objects.cc:4122
uint32_t DoubleToUint32(double x)
Definition: conversions.h:98
uint32_t HashForObject(Object *other)
Definition: objects.cc:10867
bool IsMatch(Object *string)
Definition: objects.cc:10852
static const int kMapOffset
Definition: objects.h:1219
bool ShouldConvertToSlowElements(int new_capacity)
Definition: objects.cc:10080
MUST_USE_RESULT MaybeObject * DeleteNormalizedProperty(String *name, DeleteMode mode)
Definition: objects.cc:501
int32_t DoubleToInt32(double x)
void LocalLookup(String *name, LookupResult *result)
Definition: objects.cc:4170
void IteratePrefix(ObjectVisitor *visitor)
Definition: objects.cc:11075
static HeapNumber * cast(Object *obj)
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
Definition: objects.cc:6819
MUST_USE_RESULT MaybeObject * NormalizeElements()
Definition: objects.cc:3376
static StringDictionary * cast(Object *obj)
Definition: objects.h:3153
void set_value(double value)
Definition: objects-inl.h:1195
virtual size_t length() const =0
static double nan_value()
bool is_compare_ic_stub()
Definition: objects.h:4268
void ExternalAsciiStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset, unsigned chars)
Definition: objects.cc:6450
MUST_USE_RESULT MaybeObject * AllocateAccessorPair()
Definition: heap.cc:2063
static ObjectHashTable * cast(Object *obj)
Definition: objects.h:3311
bool is_null() const
Definition: handles.h:87
#define STRUCT_LIST(V)
Definition: objects.h:429
static uint32_t RandomPrivate(Isolate *isolate)
Definition: v8.cc:178
int GetIndex(String *name, Code::Flags flags)
Definition: objects.cc:5488
AccessorDescriptor * GetCallbacks(int descriptor_number)
Definition: objects-inl.h:2030
MUST_USE_RESULT MaybeObject * SetPropertyWithHandler(JSReceiver *receiver, String *name, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: objects.cc:2531
InterceptorInfo * GetIndexedInterceptor()
Definition: objects.cc:10212
ExtraICState extra_ic_state()
Definition: objects-inl.h:3037
MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(JSReceiver *receiver, String *name)
Definition: objects.cc:2675
bool has_fast_smi_or_object_elements()
Definition: objects.h:4700
bool CanGenerateInlineConstructor(Object *prototype)
Definition: objects.cc:7703
PropertyType GetType(int descriptor_number)
Definition: objects-inl.h:2009
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:962
MUST_USE_RESULT MaybeObject * NumberFromUint32(uint32_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: heap-inl.h:237
bool Contains(Address addr)
Definition: heap.cc:5224
StaticResource< StringInputBuffer > * objects_string_input_buffer()
Definition: isolate.h:893
static bool CompileOptimized(Handle< JSFunction > function, int osr_ast_id, ClearExceptionFlag flag)
Definition: objects.cc:7480
String * hidden_symbol()
Definition: heap.h:1149
static Handle< Object > DeleteProperty(Handle< JSObject > obj, Handle< String > name)
Definition: objects.cc:3827
void BecomeJSObject(Handle< JSReceiver > object)
Definition: factory.cc:1075
#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:2790
static void ReadBlockIntoBuffer(String *input, ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned max_chars)
Definition: objects.cc:6618
static const uint32_t kHashBitMask
Definition: objects.h:7125
uint16_t uc16
Definition: globals.h:273
bool HasPropertyWithHandler(String *name)
Definition: objects.cc:2516
void AddCharacterNoIndex(uint32_t c)
Definition: objects-inl.h:4706
void SlicedStringReadBlockIntoBuffer(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6809
void HeapObjectShortPrint(StringStream *accumulator)
Definition: objects.cc:1173
PropertyDetails DetailsAt(int entry)
Definition: objects.h:3049
uint32_t ComputeLongHash(uint64_t key)
Definition: utils.h:298
Object * DeleteProperty(int entry, JSObject::DeleteMode mode)
Definition: objects.cc:12257
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:9393
PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(Object *receiver, LookupResult *result, String *name, bool continue_search)
Definition: objects.cc:365
Handle< Object > NewTypeError(const char *type, Vector< Handle< Object > > args)
Definition: factory.cc:614
MUST_USE_RESULT MaybeObject * SetPropertyWithInterceptor(String *name, Object *value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: objects.cc:1902
void set_bit_field(byte value)
Definition: objects-inl.h:2889
static Token::Value ComputeOperation(Code *target)
Definition: ic.cc:2558
static const int kMaxNumberOfDescriptors
Definition: objects.h:2657
SymbolsKey(FixedArray *symbols)
Definition: objects.cc:12114
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:7647
ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind, bool allow_only_packed)
static JSValue * cast(Object *obj)
Definition: objects-inl.h:4327
Vector< const Char > string_
Definition: objects.cc:10925
uint32_t HashSequentialString(const schar *chars, int length, uint32_t seed)
Definition: objects-inl.h:4733
bool ShouldConvertToFastElements()
Definition: objects.cc:10100
static const int kArrayIndexHashLengthShift
Definition: objects.h:7141
static const int kFieldsAdded
Definition: objects.h:2110
static const int kMaxUncheckedOldFastElementsLength
Definition: objects.h:2101
MUST_USE_RESULT MaybeObject * DefineFastAccessor(String *name, AccessorComponent component, Object *accessor, PropertyAttributes attributes)
Definition: objects.cc:4634
void ValueAtPut(int entry, Object *value)
Definition: objects.h:3044
MUST_USE_RESULT MaybeObject * AsObject()
Definition: objects.cc:5609
uint32_t HashForObject(Object *obj)
Definition: objects.cc:5430
static Handle< T > null()
Definition: handles.h:86
MaybeObject * AsObject()
Definition: objects.cc:11047
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset kThisPropertyAssignmentsOffset flag
Definition: objects-inl.h:3682
bool is_keyed_store_stub()
Definition: objects.h:4263
Object * LookupEval(String *src, Context *context, LanguageMode language_mode, int scope_position)
Definition: objects.cc:12006
Map * FindFirstMap()
Definition: objects.cc:8230
static const int kProtoTransitionPrototypeOffset
Definition: objects.h:4803
static void IncrementLiveBytesFromMutator(Address address, int by)
Definition: spaces.cc:764
#define HEAP
Definition: isolate.h:1408
virtual void Seek(unsigned pos)
Definition: objects.cc:6609
MUST_USE_RESULT MaybeObject * GetPropertyWithHandler(Object *receiver, String *name)
Definition: objects.cc:228
MUST_USE_RESULT MaybeObject * CreateNextElementsTransition(ElementsKind elements_kind)
Definition: objects.cc:2266
Object * Lookup(String *name, Code::Flags flags)
Definition: objects.cc:5457
static const int kInitialSize
Definition: objects.h:6644
MUST_USE_RESULT MaybeObject * GetProperty(String *key)
Definition: objects-inl.h:851
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
MUST_USE_RESULT MaybeObject * Put(String *src, Object *value)
Definition: objects.cc:12029
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 trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt 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 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
SubStringAsciiSymbolKey(Handle< SeqAsciiString > string, int from, int length, uint32_t seed)
Definition: objects.cc:10950
Object * extension()
Definition: contexts.h:312
const int kShortSize
Definition: globals.h:230
static bool CompileLazy(Handle< SharedFunctionInfo > shared, ClearExceptionFlag flag)
Definition: objects.cc:7458
MUST_USE_RESULT MaybeObject * Add(Object *key)
Definition: objects.cc:12713
InstanceType instance_type()
Definition: objects-inl.h:2864
MUST_USE_RESULT MaybeObject * AllocateJSGlobalPropertyCell(Object *value)
Definition: heap.cc:2443
static JSProxy * cast(Object *obj)
void SetParent(TraversableMap *parent)
Definition: objects.cc:5159
Handle< String > Uint32ToString(uint32_t value)
Definition: factory.cc:1150
static State ComputeState(Code *target)
Definition: ic.cc:2550
bool MayIndexedAccess(JSObject *receiver, uint32_t index, v8::AccessType type)
Definition: isolate.cc:851
static Handle< Object > ToNumber(Handle< Object > obj, bool *exc)
Definition: execution.cc:609
void USE(T)
Definition: globals.h:303
int NumberOfProtoTransitions()
Definition: objects.h:4806
Counters * counters()
Definition: isolate.h:804
MUST_USE_RESULT MaybeObject * OptimizeAsPrototype()
Definition: objects.cc:7503
void SetDetailsUnchecked(int descriptor_number, Smi *value)
Definition: objects-inl.h:2003
static bool EnsureCompiled(Handle< SharedFunctionInfo > shared, ClearExceptionFlag flag)
Definition: objects.cc:7438
DescriptorArray * MutatedInstanceDescriptors()
Definition: objects.cc:5170
MUST_USE_RESULT MaybeObject * CopyDropTransitions(DescriptorArray::SharedMode shared_mode)
Definition: objects.cc:4920
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 true
Definition: flags.cc:157
void EnableDeoptimizationSupport(Code *recompiled)
Definition: objects.cc:7856
bool TooManyFastProperties(int properties, StoreFromKeyed store_mode)
Definition: objects-inl.h:1609
#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 * GetPropertyWithInterceptor(JSReceiver *receiver, String *name, PropertyAttributes *attributes)
Definition: objects.cc:10254
bool IsProperty(int descriptor_number)
Definition: objects-inl.h:2037
static const int kHeaderSize
Definition: objects.h:2115
static Smi * set(Smi *smi, int bit_position, bool v)
Definition: objects.h:8752
bool used_for_prototype()
Definition: objects-inl.h:2994
bool IsCompatibleReceiver(Object *receiver)
Definition: objects-inl.h:4850
Object * SetNormalizedProperty(LookupResult *result, Object *value)
Definition: objects.cc:439
static HashTable * cast(Object *obj)
Definition: objects-inl.h:2250
void set_is_extensible(bool value)
Definition: objects-inl.h:2946
static bool CompileLazy(CompilationInfo *info)
Definition: compiler.cc:605
ElementsKind elements_kind()
Definition: objects.h:4685
MUST_USE_RESULT MaybeObject * AtNumberPut(uint32_t key, Object *value)
Definition: objects.cc:12391
Object * GetHiddenProperty(String *key)
Definition: objects.cc:3528
void set_is_shared(bool value)
Definition: objects-inl.h:2972
void SharedFunctionInfoIterateBody(ObjectVisitor *v)
Definition: objects.cc:8034
static Handle< Object > GetElement(Handle< Object > object, uint32_t index)
Definition: objects.cc:244
static Handle< Object > PreventExtensions(Handle< JSObject > object)
Definition: objects.cc:4039
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:38
bool IsEmpty() const
Definition: v8.h:208
#define FACTORY
Definition: isolate.h:1409
static const int kArrayIndexValueBits
Definition: objects.h:7134
StaticResource< Utf8Decoder > * utf8_decoder()
Definition: scanner.h:150
static void NormalizeProperties(Handle< JSObject > object, PropertyNormalizationMode mode, int expected_additional_properties)
Definition: objects.cc:3228
const uint32_t kMaxUInt32
Definition: globals.h:227
MUST_USE_RESULT MaybeObject * NumberFromInt32(int32_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: heap-inl.h:229
static Handle< JSGlobalPropertyCell > EnsurePropertyCell(Handle< GlobalObject > global, Handle< String > name)
Definition: objects.cc:11797
void SetEntry(int entry, Object *key, Object *value)
Definition: objects-inl.h:4858
static const int kFlagsIndex
Definition: objects.h:6438
MUST_USE_RESULT MaybeObject * AddSlowProperty(String *name, Object *value, PropertyAttributes attributes)
Definition: objects.cc:1682
Object * GetCallbacksObject(int descriptor_number)
Definition: objects-inl.h:2024
void Reset(Input input)
Definition: unicode-inl.h:231
Object * get(int index)
Definition: objects-inl.h:1675
int GetThisPropertyAssignmentArgument(int index)
Definition: objects.cc:7786
static VisitorId GetVisitorId(int instance_type, int instance_size)
int FindEntry(String *key)
Definition: objects.cc:11109
bool IsFastHoleyElementsKind(ElementsKind kind)
static MUST_USE_RESULT Handle< SeededNumberDictionary > Set(Handle< SeededNumberDictionary > dictionary, uint32_t index, Handle< Object > value, PropertyDetails details)
Definition: objects.cc:12397
void IterateElements(ObjectVisitor *visitor)
Definition: objects.cc:11081
CodeCacheHashTableKey(String *name, Code *code)
Definition: objects.cc:5407
bool IsNullDescriptor(int descriptor_number)
Definition: objects-inl.h:2067
MUST_USE_RESULT MaybeObject * Put(Object *key, Object *value)
Definition: objects.cc:12774
ElementsAccessor * GetElementsAccessor()
Definition: objects-inl.h:4526
Utf8SymbolKey(Vector< const char > string, uint32_t seed)
Definition: objects.cc:10849
MUST_USE_RESULT MaybeObject * JSArrayUpdateLengthFromIndex(uint32_t index, Object *value)
Definition: objects.cc:9937
void OutputToFile(FILE *out)
static const int kAttachedToSharedFunctionInfo
Definition: objects.h:5012
MUST_USE_RESULT MaybeObject * SetPrototype(Object *value, bool skip_hidden_prototypes)
Definition: objects.cc:8792
String * TryFlattenGetString(PretenureFlag pretenure=NOT_TENURED)
Definition: objects-inl.h:2292
bool HasFastArgumentsElements()
Definition: objects.cc:9246
MUST_USE_RESULT MaybeObject * LookupString(String *key, Object **s)
Definition: objects.cc:11834
void set_bit_field2(byte value)
Definition: objects-inl.h:2899
static MUST_USE_RESULT MaybeObject * AsObject(uint32_t key)
Definition: objects-inl.h:4908
static void UpdateMapCodeCache(Handle< JSObject > object, Handle< String > name, Handle< Code > code)
Definition: objects.cc:3201
void CreateFillerObjectAt(Address addr, int size)
Definition: heap.cc:3447
void SwapPairs(FixedArray *numbers, int i, int j)
Definition: objects.cc:10397
Object * RemovePrototype()
Definition: objects.cc:7609
const char * name_
Definition: flags.cc:1352
AsciiSymbolKey(Vector< const char > str, uint32_t seed)
Definition: objects.cc:10934
void set(AccessorComponent component, Object *value)
Definition: objects.h:8226
static const int kMaxCapacity
Definition: objects.h:2854
static int Decode(FILE *f, byte *begin, byte *end)
static uint32_t RegExpHash(String *string, Smi *flags)
Definition: objects.cc:10838
JSFunction * closure()
Definition: contexts.h:301
int NumberOfLocalProperties(PropertyAttributes filter=NONE)
Definition: objects.cc:10390
static void FlushICache(void *start, size_t size)
bool IsEqualTo(Vector< const char > str)
Definition: objects.cc:7091
static ExternalByteArray * cast(Object *obj)
MUST_USE_RESULT MaybeObject * AtPut(Key key, Object *value)
Definition: objects.cc:12278
static const int kMaxUncheckedFastElementsLength
Definition: objects.h:2097
Definition: objects.h:6746
Handle< Boolean >(* IndexedPropertyDeleter)(uint32_t index, const AccessorInfo &info)
Definition: v8.h:2088
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: v8utils.h:114
const int kMaxKeyedPolymorphism
Definition: type-info.h:39
static Flags RemoveTypeFromFlags(Flags flags)
Definition: objects-inl.h:3374
void LocalLookupRealNamedProperty(String *name, LookupResult *result)
Definition: objects.cc:2369
static int DaysFromTime(int64_t time_ms)
Definition: date.h:77
bool is_keyed_call_stub()
Definition: objects.h:4265
V8EXPORT bool IsInt32() const
Definition: api.cc:2197
int aliased_context_slot()
void JSFunctionIterateBody(int object_size, ObjectVisitor *v)
Definition: objects.cc:7420
void set_this_property_assignments_count(int value)
const uint32_t kAsciiStringTag
Definition: objects.h:451
void CopyChars(sinkchar *dest, const sourcechar *src, int chars)
Definition: v8utils.h:208
String * GetThisPropertyAssignmentName(int index)
Definition: objects.cc:7767
static const int kConstructStubOffset
Definition: objects.h:5608
static const int kHashShift
Definition: objects.h:7121
AccessorDescriptor * FindAccessor(String *name)
Definition: objects.cc:4159
MUST_USE_RESULT MaybeObject * DeleteProperty(String *name, DeleteMode mode)
Definition: objects.cc:3900
static bool EncodeAsciiCharacter(uchar c, byte *buffer, unsigned capacity, unsigned &offset)
Definition: unicode-inl.h:160
MUST_USE_RESULT MaybeObject * Shrink(Key key)
Definition: objects.cc:11233
MUST_USE_RESULT MaybeObject * GetHash(CreationFlag flag)
Definition: objects.cc:740
static const char * GetStateName(State state)
Definition: ic.cc:2564
static ConsString * cast(Object *obj)
uint32_t HashForObject(Object *obj)
Definition: objects.cc:10771
bool HasDictionaryArgumentsElements()
Definition: objects.cc:9258
void JSObjectShortPrint(StringStream *accumulator)
Definition: objects.cc:1072
static CodeCache * cast(Object *obj)
static int NewElementsCapacity(int old_capacity)
Definition: objects.h:1748
bool IsIdentifierStart(unibrow::uchar c)
Definition: scanner.h:154
static FixedArrayBase * cast(Object *object)
Definition: objects-inl.h:1669
unsigned char byte
Definition: unicode.h:41
MUST_USE_RESULT MaybeObject * LookupSymbol(Vector< const char > str, Object **s)
Definition: objects.cc:11934
void StringShortPrint(StringStream *accumulator)
Definition: objects.cc:1009
void ClearNonLiveTransitions(Heap *heap)
Definition: objects.cc:7319
Object * GetComponent(AccessorComponent component)
Definition: objects.cc:6078
uint32_t HashForObject(Object *key)
Definition: objects.cc:11885
static const int kMaxValue
Definition: objects.h:1006
int NextFreePropertyIndex()
Definition: objects.cc:4146
static const int kCodeCacheOffset
Definition: objects.h:4966
const unibrow::byte * SlicedStringReadBlock(ReadBlockBuffer *buffer, unsigned *offset_ptr, unsigned chars)
Definition: objects.cc:6798
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11728
static ExternalUnsignedIntArray * cast(Object *obj)
static MUST_USE_RESULT MaybeObject * Allocate(int number_of_deopt_points, PretenureFlag pretenure)
Definition: objects.cc:6092
static const int kNotFound
Definition: objects.h:2606
static void DefineAccessor(Handle< JSObject > object, Handle< String > name, Handle< Object > getter, Handle< Object > setter, PropertyAttributes attributes)
Definition: objects.cc:4480
void set_non_instance_prototype(bool value)
Definition: objects-inl.h:2904
virtual MUST_USE_RESULT MaybeObject * SetLength(JSArray *holder, Object *new_length)=0
const uc32 kMaxAsciiCharCode
Definition: globals.h:277
MUST_USE_RESULT MaybeObject * Remove(Object *key)
Definition: objects.cc:12740
Handle< Value >(* AccessorGetter)(Local< String > property, const AccessorInfo &info)
Definition: v8.h:1424
Handle< Object > NewNumberFromUint(uint32_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:597
MUST_USE_RESULT MaybeObject * AllocateMap(InstanceType instance_type, int instance_size, ElementsKind elements_kind=TERMINAL_FAST_ELEMENTS_KIND)
Definition: heap.cc:2011
#define ARRAY_SIZE(a)
Definition: globals.h:295
StringDictionary * property_dictionary()
Definition: objects-inl.h:4626
const int kCharSize
Definition: globals.h:229
MUST_USE_RESULT MaybeObject * AsObject()
Definition: objects.cc:10785
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
MUST_USE_RESULT MaybeObject * CopySize(int new_length)
Definition: objects.cc:5711
void TraverseTransitionTree(TraverseCallback callback, void *data)
Definition: objects.cc:5212
void SetNoStackCheckTable()
Definition: objects.cc:8223
MUST_USE_RESULT MaybeObject * ReplaceSlowProperty(String *name, Object *value, PropertyAttributes attributes)
Definition: objects.cc:1785
void UpdateMaxNumberKey(uint32_t key)
Definition: objects.cc:12350
void SetNextEnumerationIndex(int value)
Definition: objects.h:2454
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11722
static ObjectHashSet * cast(Object *obj)
Definition: objects.h:3291
static JSObject * cast(Object *obj)
void ClearInlineCaches()
Definition: objects.cc:8243
static const int kMaxArrayIndexSize
Definition: objects.h:7104
FlagType type() const
Definition: flags.cc:1358
static const char *const kTagNames[kNumberOfSyncTags]
Definition: objects.h:8665
static void Clear(Address address)
Definition: ic.cc:340
static MUST_USE_RESULT MaybeObject * Allocate(int number_of_descriptors, SharedMode shared_mode)
Definition: objects.cc:5754
PropertyAttributes GetLocalPropertyAttribute(String *name)
Definition: objects.cc:3134
static const int kNoPreviousCharacter
Definition: unicode.h:132
void BecomeJSFunction(Handle< JSReceiver > object)
Definition: factory.cc:1083
static InterceptorInfo * cast(Object *obj)
MUST_USE_RESULT MaybeObject * SetValue(uint32_t index, Object *value)
Definition: objects.cc:11708
bool IsFastDoubleElementsKind(ElementsKind kind)
MUST_USE_RESULT MaybeObject * EnsureCanContainElements(Object **elements, uint32_t count, EnsureElementsMode mode)
Definition: objects-inl.h:1260
MUST_USE_RESULT MaybeObject * SubString(int from, int to, PretenureFlag pretenure=NOT_TENURED)
Definition: objects.cc:7292
void set_unused_property_fields(int value)
Definition: objects-inl.h:2879
bool is_keyed_load_stub()
Definition: objects.h:4261
Object * FindInCodeCache(String *name, Code::Flags flags)
Definition: objects.cc:4961
const uint32_t kStringEncodingMask
Definition: objects.h:449
static v8::internal::Handle< v8::internal::TemplateInfo > OpenHandle(const Template *that)
Object * Lookup(FixedArray *key)
Definition: objects.cc:12145
MUST_USE_RESULT MaybeObject * AtNumberPut(uint32_t key, Object *value)
Definition: objects.cc:12385
static MUST_USE_RESULT Handle< UnseededNumberDictionary > Set(Handle< UnseededNumberDictionary > dictionary, uint32_t index, Handle< Object > value)
Definition: objects.cc:12408
void SetComponents(Object *getter, Object *setter)
Definition: objects.h:8238
void set_stack_check_table_offset(unsigned offset)
Definition: objects-inl.h:3202
Handle< Boolean >(* NamedPropertyDeleter)(Local< String > property, const AccessorInfo &info)
Definition: v8.h:2049
void set_bit_field3(int value)
Definition: objects-inl.h:3478
static DeoptimizationInputData * cast(Object *obj)
int64_t ToLocal(int64_t time_ms)
Definition: date.h:126
Object * GetThisPropertyAssignmentConstant(int index)
Definition: objects.cc:7794
MUST_USE_RESULT MaybeObject * AllocateAliasedArgumentsEntry(int slot)
Definition: heap.cc:2087
IntrusivePrototypeTransitionIterator(HeapObject *proto_trans)
Definition: objects.cc:5078
String * constructor_name()
Definition: objects.cc:1473
bool IsAsciiEqualTo(Vector< const char > str)
Definition: objects.cc:7112
static JSGlobalObject * cast(Object *obj)
void StartInobjectSlackTracking(Map *map)
Definition: objects.cc:7907
static JSFunction * cast(Object *obj)