~yolanda.robla/ubuntu/trusty/nodejs/add_distribution

« back to all changes in this revision

Viewing changes to deps/v8/src/handles.cc

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2013-08-14 00:16:46 UTC
  • mfrom: (7.1.40 sid)
  • Revision ID: package-import@ubuntu.com-20130814001646-bzlysfh8sd6mukbo
Tags: 0.10.15~dfsg1-4
* Update 2005 patch, adding a handful of tests that can fail on
  slow platforms.
* Add 1004 patch to fix test failures when writing NaN to buffer
  on mipsel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2011 the V8 project authors. All rights reserved.
 
1
// Copyright 2012 the V8 project authors. All rights reserved.
2
2
// Redistribution and use in source and binary forms, with or without
3
3
// modification, are permitted provided that the following conditions are
4
4
// met:
165
165
  func->shared()->set_expected_nof_properties(nof);
166
166
  if (func->has_initial_map()) {
167
167
    Handle<Map> new_initial_map =
168
 
        func->GetIsolate()->factory()->CopyMapDropTransitions(
 
168
        func->GetIsolate()->factory()->CopyMap(
169
169
            Handle<Map>(func->initial_map()));
170
170
    new_initial_map->set_unused_property_fields(nof);
171
171
    func->set_initial_map(*new_initial_map);
190
190
 
191
191
  // Inobject slack tracking will reclaim redundant inobject space later,
192
192
  // so we can afford to adjust the estimate generously.
193
 
  return estimate + 8;
 
193
  if (FLAG_clever_optimizations) {
 
194
    return estimate + 8;
 
195
  } else {
 
196
    return estimate + 3;
 
197
  }
194
198
}
195
199
 
196
200
 
204
208
}
205
209
 
206
210
 
207
 
void NormalizeProperties(Handle<JSObject> object,
208
 
                         PropertyNormalizationMode mode,
209
 
                         int expected_additional_properties) {
210
 
  CALL_HEAP_FUNCTION_VOID(object->GetIsolate(),
211
 
                          object->NormalizeProperties(
212
 
                              mode,
213
 
                              expected_additional_properties));
214
 
}
215
 
 
216
 
 
217
 
Handle<SeededNumberDictionary> NormalizeElements(Handle<JSObject> object) {
218
 
  CALL_HEAP_FUNCTION(object->GetIsolate(),
219
 
                     object->NormalizeElements(),
220
 
                     SeededNumberDictionary);
221
 
}
222
 
 
223
 
 
224
 
void TransformToFastProperties(Handle<JSObject> object,
225
 
                               int unused_property_fields) {
226
 
  CALL_HEAP_FUNCTION_VOID(
227
 
      object->GetIsolate(),
228
 
      object->TransformToFastProperties(unused_property_fields));
229
 
}
230
 
 
231
 
 
232
 
Handle<SeededNumberDictionary> SeededNumberDictionarySet(
233
 
    Handle<SeededNumberDictionary> dictionary,
234
 
    uint32_t index,
235
 
    Handle<Object> value,
236
 
    PropertyDetails details) {
237
 
  CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
238
 
                     dictionary->Set(index, *value, details),
239
 
                     SeededNumberDictionary);
240
 
}
241
 
 
242
 
 
243
211
void FlattenString(Handle<String> string) {
244
212
  CALL_HEAP_FUNCTION_VOID(string->GetIsolate(), string->TryFlatten());
245
213
}
261
229
}
262
230
 
263
231
 
264
 
Handle<Object> SetProperty(Handle<JSReceiver> object,
265
 
                           Handle<String> key,
266
 
                           Handle<Object> value,
267
 
                           PropertyAttributes attributes,
268
 
                           StrictModeFlag strict_mode) {
269
 
  CALL_HEAP_FUNCTION(object->GetIsolate(),
270
 
                     object->SetProperty(*key, *value, attributes, strict_mode),
271
 
                     Object);
272
 
}
273
 
 
274
 
 
275
232
Handle<Object> SetProperty(Handle<Object> object,
276
233
                           Handle<Object> key,
277
234
                           Handle<Object> value,
299
256
}
300
257
 
301
258
 
302
 
Handle<Object> SetNormalizedProperty(Handle<JSObject> object,
303
 
                                     Handle<String> key,
304
 
                                     Handle<Object> value,
305
 
                                     PropertyDetails details) {
306
 
  CALL_HEAP_FUNCTION(object->GetIsolate(),
307
 
                     object->SetNormalizedProperty(*key, *value, details),
308
 
                     Object);
309
 
}
310
 
 
311
 
 
312
259
Handle<Object> ForceDeleteProperty(Handle<JSObject> object,
313
260
                                   Handle<Object> key) {
314
261
  Isolate* isolate = object->GetIsolate();
318
265
}
319
266
 
320
267
 
321
 
Handle<Object> SetLocalPropertyIgnoreAttributes(
322
 
    Handle<JSObject> object,
323
 
    Handle<String> key,
324
 
    Handle<Object> value,
325
 
    PropertyAttributes attributes) {
326
 
  CALL_HEAP_FUNCTION(
327
 
    object->GetIsolate(),
328
 
    object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
329
 
    Object);
330
 
}
331
 
 
332
 
 
333
 
void SetLocalPropertyNoThrow(Handle<JSObject> object,
334
 
                             Handle<String> key,
335
 
                             Handle<Object> value,
336
 
                             PropertyAttributes attributes) {
337
 
  Isolate* isolate = object->GetIsolate();
338
 
  ASSERT(!isolate->has_pending_exception());
339
 
  CHECK(!SetLocalPropertyIgnoreAttributes(
340
 
        object, key, value, attributes).is_null());
341
 
  CHECK(!isolate->has_pending_exception());
342
 
}
343
 
 
344
 
 
345
268
Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
346
269
                                          Handle<String> key,
347
270
                                          Handle<Object> value,
372
295
}
373
296
 
374
297
 
375
 
Handle<Object> GetProperty(Handle<JSReceiver> obj,
376
 
                           Handle<String> name,
377
 
                           LookupResult* result) {
378
 
  PropertyAttributes attributes;
379
 
  Isolate* isolate = Isolate::Current();
380
 
  CALL_HEAP_FUNCTION(isolate,
381
 
                     obj->GetProperty(*obj, result, *name, &attributes),
382
 
                     Object);
383
 
}
384
 
 
385
 
 
386
 
Handle<Object> GetElement(Handle<Object> obj,
387
 
                          uint32_t index) {
388
 
  Isolate* isolate = Isolate::Current();
389
 
  CALL_HEAP_FUNCTION(isolate, Runtime::GetElement(obj, index), Object);
390
 
}
391
 
 
392
 
 
393
298
Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
394
299
                                          Handle<JSObject> holder,
395
300
                                          Handle<String> name,
403
308
}
404
309
 
405
310
 
406
 
Handle<Object> GetPrototype(Handle<Object> obj) {
407
 
  Handle<Object> result(obj->GetPrototype());
408
 
  return result;
409
 
}
410
 
 
411
 
 
412
311
Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value) {
413
312
  const bool skip_hidden_prototypes = false;
414
313
  CALL_HEAP_FUNCTION(obj->GetIsolate(),
416
315
}
417
316
 
418
317
 
419
 
Handle<Object> PreventExtensions(Handle<JSObject> object) {
420
 
  CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object);
421
 
}
422
 
 
423
 
 
424
 
Handle<Object> GetHiddenProperties(Handle<JSObject> obj,
425
 
                                   JSObject::HiddenPropertiesFlag flag) {
426
 
  CALL_HEAP_FUNCTION(obj->GetIsolate(),
427
 
                     obj->GetHiddenProperties(flag),
428
 
                     Object);
429
 
}
430
 
 
431
 
 
432
 
int GetIdentityHash(Handle<JSObject> obj) {
433
 
  CALL_AND_RETRY(obj->GetIsolate(),
434
 
                 obj->GetIdentityHash(JSObject::ALLOW_CREATION),
435
 
                 return Smi::cast(__object__)->value(),
436
 
                 return 0);
437
 
}
438
 
 
439
 
 
440
 
Handle<Object> DeleteElement(Handle<JSObject> obj,
441
 
                             uint32_t index) {
442
 
  CALL_HEAP_FUNCTION(obj->GetIsolate(),
443
 
                     obj->DeleteElement(index, JSObject::NORMAL_DELETION),
444
 
                     Object);
445
 
}
446
 
 
447
 
 
448
 
Handle<Object> DeleteProperty(Handle<JSObject> obj,
449
 
                              Handle<String> prop) {
450
 
  CALL_HEAP_FUNCTION(obj->GetIsolate(),
451
 
                     obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
452
 
                     Object);
453
 
}
454
 
 
455
 
 
456
318
Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index) {
457
319
  Isolate* isolate = Isolate::Current();
458
320
  CALL_HEAP_FUNCTION(
470
332
}
471
333
 
472
334
 
473
 
Handle<Object> SetElement(Handle<JSObject> object,
474
 
                          uint32_t index,
475
 
                          Handle<Object> value,
476
 
                          StrictModeFlag strict_mode) {
477
 
  if (object->HasExternalArrayElements()) {
478
 
    if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
479
 
      bool has_exception;
480
 
      Handle<Object> number = Execution::ToNumber(value, &has_exception);
481
 
      if (has_exception) return Handle<Object>();
482
 
      value = number;
483
 
    }
484
 
  }
485
 
  CALL_HEAP_FUNCTION(object->GetIsolate(),
486
 
                     object->SetElement(index, *value, strict_mode, true),
487
 
                     Object);
488
 
}
489
 
 
490
 
 
491
 
Handle<Object> SetOwnElement(Handle<JSObject> object,
492
 
                             uint32_t index,
493
 
                             Handle<Object> value,
494
 
                             StrictModeFlag strict_mode) {
495
 
  ASSERT(!object->HasExternalArrayElements());
496
 
  CALL_HEAP_FUNCTION(object->GetIsolate(),
497
 
                     object->SetElement(index, *value, strict_mode, false),
498
 
                     Object);
499
 
}
500
 
 
501
 
 
502
335
Handle<JSObject> Copy(Handle<JSObject> obj) {
503
336
  Isolate* isolate = obj->GetIsolate();
504
337
  CALL_HEAP_FUNCTION(isolate,
521
354
  Handle<Object> cache = Utils::OpenHandle(*handle);
522
355
  JSValue* wrapper = JSValue::cast(*cache);
523
356
  Foreign* foreign = Script::cast(wrapper->value())->wrapper();
524
 
  ASSERT(foreign->address() == reinterpret_cast<Address>(cache.location()));
525
 
  foreign->set_address(0);
 
357
  ASSERT(foreign->foreign_address() ==
 
358
         reinterpret_cast<Address>(cache.location()));
 
359
  foreign->set_foreign_address(0);
526
360
  Isolate* isolate = Isolate::Current();
527
361
  isolate->global_handles()->Destroy(cache.location());
528
362
  isolate->counters()->script_wrappers()->Decrement();
530
364
 
531
365
 
532
366
Handle<JSValue> GetScriptWrapper(Handle<Script> script) {
533
 
  if (script->wrapper()->address() != NULL) {
 
367
  if (script->wrapper()->foreign_address() != NULL) {
534
368
    // Return the script wrapper directly from the cache.
535
369
    return Handle<JSValue>(
536
 
        reinterpret_cast<JSValue**>(script->wrapper()->address()));
 
370
        reinterpret_cast<JSValue**>(script->wrapper()->foreign_address()));
537
371
  }
538
372
  Isolate* isolate = Isolate::Current();
539
373
  // Construct a new script wrapper.
549
383
  Handle<Object> handle = isolate->global_handles()->Create(*result);
550
384
  isolate->global_handles()->MakeWeak(handle.location(), NULL,
551
385
                                      &ClearWrapperCache);
552
 
  script->wrapper()->set_address(reinterpret_cast<Address>(handle.location()));
 
386
  script->wrapper()->set_foreign_address(
 
387
      reinterpret_cast<Address>(handle.location()));
553
388
  return result;
554
389
}
555
390
 
665
500
  return right + script->line_offset()->value();
666
501
}
667
502
 
 
503
// Convert code position into column number.
 
504
int GetScriptColumnNumber(Handle<Script> script, int code_pos) {
 
505
  int line_number = GetScriptLineNumber(script, code_pos);
 
506
  if (line_number == -1) return -1;
 
507
 
 
508
  AssertNoAllocation no_allocation;
 
509
  FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
 
510
  line_number = line_number - script->line_offset()->value();
 
511
  if (line_number == 0) return code_pos + script->column_offset()->value();
 
512
  int prev_line_end_pos =
 
513
      Smi::cast(line_ends_array->get(line_number - 1))->value();
 
514
  return code_pos - (prev_line_end_pos + 1);
 
515
}
668
516
 
669
517
int GetScriptLineNumberSafe(Handle<Script> script, int code_pos) {
670
518
  AssertNoAllocation no_allocation;
696
544
 
697
545
 
698
546
// Compute the property keys from the interceptor.
699
 
v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver,
 
547
v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSReceiver> receiver,
700
548
                                                 Handle<JSObject> object) {
701
549
  Isolate* isolate = receiver->GetIsolate();
702
550
  Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
713
561
      result = enum_fun(info);
714
562
    }
715
563
  }
 
564
#if ENABLE_EXTRA_CHECKS
 
565
  CHECK(result.IsEmpty() || v8::Utils::OpenHandle(*result)->IsJSObject());
 
566
#endif
716
567
  return result;
717
568
}
718
569
 
719
570
 
720
571
// Compute the element keys from the interceptor.
721
 
v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
 
572
v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSReceiver> receiver,
722
573
                                                   Handle<JSObject> object) {
723
574
  Isolate* isolate = receiver->GetIsolate();
724
575
  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
733
584
      // Leaving JavaScript.
734
585
      VMState state(isolate, EXTERNAL);
735
586
      result = enum_fun(info);
 
587
#if ENABLE_EXTRA_CHECKS
 
588
      CHECK(result.IsEmpty() || v8::Utils::OpenHandle(*result)->IsJSObject());
 
589
#endif
736
590
    }
737
591
  }
738
592
  return result;
749
603
}
750
604
 
751
605
 
752
 
Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
753
 
                                          KeyCollectionType type) {
 
606
Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSReceiver> object,
 
607
                                          KeyCollectionType type,
 
608
                                          bool* threw) {
754
609
  USE(ContainsOnlyValidKeys);
755
610
  Isolate* isolate = object->GetIsolate();
756
611
  Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
757
612
  Handle<JSObject> arguments_boilerplate = Handle<JSObject>(
758
 
      isolate->context()->global_context()->arguments_boilerplate(),
 
613
      isolate->context()->native_context()->arguments_boilerplate(),
759
614
      isolate);
760
615
  Handle<JSFunction> arguments_function = Handle<JSFunction>(
761
616
      JSFunction::cast(arguments_boilerplate->map()->constructor()),
765
620
  for (Handle<Object> p = object;
766
621
       *p != isolate->heap()->null_value();
767
622
       p = Handle<Object>(p->GetPrototype(), isolate)) {
 
623
    if (p->IsJSProxy()) {
 
624
      Handle<JSProxy> proxy(JSProxy::cast(*p), isolate);
 
625
      Handle<Object> args[] = { proxy };
 
626
      Handle<Object> names = Execution::Call(
 
627
          isolate->proxy_enumerate(), object, ARRAY_SIZE(args), args, threw);
 
628
      if (*threw) return content;
 
629
      content = AddKeysFromJSArray(content, Handle<JSArray>::cast(names));
 
630
      break;
 
631
    }
 
632
 
768
633
    Handle<JSObject> current(JSObject::cast(*p), isolate);
769
634
 
770
635
    // Check access rights if required.
831
696
}
832
697
 
833
698
 
834
 
Handle<JSArray> GetKeysFor(Handle<JSObject> object) {
 
699
Handle<JSArray> GetKeysFor(Handle<JSReceiver> object, bool* threw) {
835
700
  Isolate* isolate = object->GetIsolate();
836
701
  isolate->counters()->for_in()->Increment();
837
 
  Handle<FixedArray> elements = GetKeysInFixedArrayFor(object,
838
 
                                                       INCLUDE_PROTOS);
 
702
  Handle<FixedArray> elements =
 
703
      GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, threw);
839
704
  return isolate->factory()->NewJSArrayWithElements(elements);
840
705
}
841
706
 
842
707
 
 
708
Handle<FixedArray> ReduceFixedArrayTo(Handle<FixedArray> array, int length) {
 
709
  ASSERT(array->length() >= length);
 
710
  if (array->length() == length) return array;
 
711
 
 
712
  Handle<FixedArray> new_array =
 
713
      array->GetIsolate()->factory()->NewFixedArray(length);
 
714
  for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
 
715
  return new_array;
 
716
}
 
717
 
 
718
 
843
719
Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
844
720
                                       bool cache_result) {
845
 
  int index = 0;
846
721
  Isolate* isolate = object->GetIsolate();
847
722
  if (object->HasFastProperties()) {
848
723
    if (object->map()->instance_descriptors()->HasEnumCache()) {
 
724
      int own_property_count = object->map()->EnumLength();
 
725
      // If we have an enum cache, but the enum length of the given map is set
 
726
      // to kInvalidEnumCache, this means that the map itself has never used the
 
727
      // present enum cache. The first step to using the cache is to set the
 
728
      // enum length of the map by counting the number of own descriptors that
 
729
      // are not DONT_ENUM.
 
730
      if (own_property_count == Map::kInvalidEnumCache) {
 
731
        own_property_count = object->map()->NumberOfDescribedProperties(
 
732
            OWN_DESCRIPTORS, DONT_ENUM);
 
733
 
 
734
        if (cache_result) object->map()->SetEnumLength(own_property_count);
 
735
      }
 
736
 
 
737
      DescriptorArray* desc = object->map()->instance_descriptors();
 
738
      Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
 
739
 
 
740
      // In case the number of properties required in the enum are actually
 
741
      // present, we can reuse the enum cache. Otherwise, this means that the
 
742
      // enum cache was generated for a previous (smaller) version of the
 
743
      // Descriptor Array. In that case we regenerate the enum cache.
 
744
      if (own_property_count <= keys->length()) {
 
745
        isolate->counters()->enum_cache_hits()->Increment();
 
746
        return ReduceFixedArrayTo(keys, own_property_count);
 
747
      }
 
748
    }
 
749
 
 
750
    Handle<Map> map(object->map());
 
751
 
 
752
    if (map->instance_descriptors()->IsEmpty()) {
849
753
      isolate->counters()->enum_cache_hits()->Increment();
850
 
      DescriptorArray* desc = object->map()->instance_descriptors();
851
 
      return Handle<FixedArray>(FixedArray::cast(desc->GetEnumCache()),
852
 
                                isolate);
 
754
      if (cache_result) map->SetEnumLength(0);
 
755
      return isolate->factory()->empty_fixed_array();
853
756
    }
 
757
 
854
758
    isolate->counters()->enum_cache_misses()->Increment();
855
 
    int num_enum = object->NumberOfEnumProperties();
 
759
    int num_enum = map->NumberOfDescribedProperties(ALL_DESCRIPTORS, DONT_ENUM);
 
760
 
856
761
    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum);
857
 
    Handle<FixedArray> sort_array = isolate->factory()->NewFixedArray(num_enum);
 
762
    Handle<FixedArray> indices = isolate->factory()->NewFixedArray(num_enum);
 
763
 
858
764
    Handle<DescriptorArray> descs =
859
765
        Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
 
766
 
 
767
    int real_size = map->NumberOfOwnDescriptors();
 
768
    int enum_size = 0;
 
769
    int index = 0;
 
770
 
860
771
    for (int i = 0; i < descs->number_of_descriptors(); i++) {
861
 
      if (descs->IsProperty(i) && !descs->IsDontEnum(i)) {
862
 
        (*storage)->set(index, descs->GetKey(i));
863
 
        PropertyDetails details(descs->GetDetails(i));
864
 
        (*sort_array)->set(index, Smi::FromInt(details.index()));
 
772
      PropertyDetails details = descs->GetDetails(i);
 
773
      if (!details.IsDontEnum()) {
 
774
        if (i < real_size) ++enum_size;
 
775
        storage->set(index, descs->GetKey(i));
 
776
        if (!indices.is_null()) {
 
777
          if (details.type() != FIELD) {
 
778
            indices = Handle<FixedArray>();
 
779
          } else {
 
780
            int field_index = Descriptor::IndexFromValue(descs->GetValue(i));
 
781
            if (field_index >= map->inobject_properties()) {
 
782
              field_index = -(field_index - map->inobject_properties() + 1);
 
783
            }
 
784
            indices->set(index, Smi::FromInt(field_index));
 
785
          }
 
786
        }
865
787
        index++;
866
788
      }
867
789
    }
868
 
    (*storage)->SortPairs(*sort_array, sort_array->length());
 
790
    ASSERT(index == storage->length());
 
791
 
 
792
    Handle<FixedArray> bridge_storage =
 
793
        isolate->factory()->NewFixedArray(
 
794
            DescriptorArray::kEnumCacheBridgeLength);
 
795
    DescriptorArray* desc = object->map()->instance_descriptors();
 
796
    desc->SetEnumCache(*bridge_storage,
 
797
                       *storage,
 
798
                       indices.is_null() ? Object::cast(Smi::FromInt(0))
 
799
                                         : Object::cast(*indices));
869
800
    if (cache_result) {
870
 
      Handle<FixedArray> bridge_storage =
871
 
          isolate->factory()->NewFixedArray(
872
 
              DescriptorArray::kEnumCacheBridgeLength);
873
 
      DescriptorArray* desc = object->map()->instance_descriptors();
874
 
      desc->SetEnumCache(*bridge_storage, *storage);
 
801
      object->map()->SetEnumLength(enum_size);
875
802
    }
876
 
    ASSERT(storage->length() == index);
877
 
    return storage;
 
803
 
 
804
    return ReduceFixedArrayTo(storage, enum_size);
878
805
  } else {
879
 
    int num_enum = object->NumberOfEnumProperties();
880
 
    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum);
881
 
    Handle<FixedArray> sort_array = isolate->factory()->NewFixedArray(num_enum);
882
 
    object->property_dictionary()->CopyEnumKeysTo(*storage, *sort_array);
 
806
    Handle<StringDictionary> dictionary(object->property_dictionary());
 
807
 
 
808
    int length = dictionary->NumberOfElements();
 
809
    if (length == 0) {
 
810
      return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
 
811
    }
 
812
 
 
813
    // The enumeration array is generated by allocating an array big enough to
 
814
    // hold all properties that have been seen, whether they are are deleted or
 
815
    // not. Subsequently all visible properties are added to the array. If some
 
816
    // properties were not visible, the array is trimmed so it only contains
 
817
    // visible properties. This improves over adding elements and sorting by
 
818
    // index by having linear complexity rather than n*log(n).
 
819
 
 
820
    // By comparing the monotonous NextEnumerationIndex to the NumberOfElements,
 
821
    // we can predict the number of holes in the final array. If there will be
 
822
    // more than 50% holes, regenerate the enumeration indices to reduce the
 
823
    // number of holes to a minimum. This avoids allocating a large array if
 
824
    // many properties were added but subsequently deleted.
 
825
    int next_enumeration = dictionary->NextEnumerationIndex();
 
826
    if (!object->IsGlobalObject() && next_enumeration > (length * 3) / 2) {
 
827
      StringDictionary::DoGenerateNewEnumerationIndices(dictionary);
 
828
      next_enumeration = dictionary->NextEnumerationIndex();
 
829
    }
 
830
 
 
831
    Handle<FixedArray> storage =
 
832
        isolate->factory()->NewFixedArray(next_enumeration);
 
833
 
 
834
    storage = Handle<FixedArray>(dictionary->CopyEnumKeysTo(*storage));
 
835
    ASSERT(storage->length() == object->NumberOfLocalProperties(DONT_ENUM));
883
836
    return storage;
884
837
  }
885
838
}
886
839
 
887
840
 
 
841
Handle<ObjectHashSet> ObjectHashSetAdd(Handle<ObjectHashSet> table,
 
842
                                       Handle<Object> key) {
 
843
  CALL_HEAP_FUNCTION(table->GetIsolate(),
 
844
                     table->Add(*key),
 
845
                     ObjectHashSet);
 
846
}
 
847
 
 
848
 
 
849
Handle<ObjectHashSet> ObjectHashSetRemove(Handle<ObjectHashSet> table,
 
850
                                          Handle<Object> key) {
 
851
  CALL_HEAP_FUNCTION(table->GetIsolate(),
 
852
                     table->Remove(*key),
 
853
                     ObjectHashSet);
 
854
}
 
855
 
 
856
 
888
857
Handle<ObjectHashTable> PutIntoObjectHashTable(Handle<ObjectHashTable> table,
889
 
                                               Handle<JSObject> key,
 
858
                                               Handle<Object> key,
890
859
                                               Handle<Object> value) {
891
860
  CALL_HEAP_FUNCTION(table->GetIsolate(),
892
861
                     table->Put(*key, *value),
894
863
}
895
864
 
896
865
 
897
 
bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
898
 
                    ClearExceptionFlag flag) {
899
 
  return shared->is_compiled() || CompileLazyShared(shared, flag);
900
 
}
901
 
 
902
 
 
903
 
static bool CompileLazyHelper(CompilationInfo* info,
904
 
                              ClearExceptionFlag flag) {
905
 
  // Compile the source information to a code object.
906
 
  ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
907
 
  ASSERT(!info->isolate()->has_pending_exception());
908
 
  bool result = Compiler::CompileLazy(info);
909
 
  ASSERT(result != Isolate::Current()->has_pending_exception());
910
 
  if (!result && flag == CLEAR_EXCEPTION) {
911
 
    info->isolate()->clear_pending_exception();
912
 
  }
913
 
  return result;
914
 
}
915
 
 
916
 
 
917
 
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
918
 
                       ClearExceptionFlag flag) {
919
 
  CompilationInfo info(shared);
920
 
  return CompileLazyHelper(&info, flag);
921
 
}
922
 
 
923
 
 
924
 
bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag) {
925
 
  bool result = true;
926
 
  if (function->shared()->is_compiled()) {
927
 
    function->ReplaceCode(function->shared()->code());
928
 
    function->shared()->set_code_age(0);
929
 
  } else {
930
 
    CompilationInfo info(function);
931
 
    result = CompileLazyHelper(&info, flag);
932
 
    ASSERT(!result || function->is_compiled());
933
 
  }
934
 
  return result;
935
 
}
936
 
 
937
 
 
938
 
bool CompileOptimized(Handle<JSFunction> function,
939
 
                      int osr_ast_id,
940
 
                      ClearExceptionFlag flag) {
941
 
  CompilationInfo info(function);
942
 
  info.SetOptimizing(osr_ast_id);
943
 
  return CompileLazyHelper(&info, flag);
944
 
}
 
866
// This method determines the type of string involved and then gets the UTF8
 
867
// length of the string.  It doesn't flatten the string and has log(n) recursion
 
868
// for a string of length n.  If the failure flag gets set, then we have to
 
869
// flatten the string and retry.  Failures are caused by surrogate pairs in deep
 
870
// cons strings.
 
871
 
 
872
// Single surrogate characters that are encountered in the UTF-16 character
 
873
// sequence of the input string get counted as 3 UTF-8 bytes, because that
 
874
// is the way that WriteUtf8 will encode them.  Surrogate pairs are counted and
 
875
// encoded as one 4-byte UTF-8 sequence.
 
876
 
 
877
// This function conceptually uses recursion on the two halves of cons strings.
 
878
// However, in order to avoid the recursion going too deep it recurses on the
 
879
// second string of the cons, but iterates on the first substring (by manually
 
880
// eliminating it as a tail recursion).  This means it counts the UTF-8 length
 
881
// from the end to the start, which makes no difference to the total.
 
882
 
 
883
// Surrogate pairs are recognized even if they are split across two sides of a
 
884
// cons, which complicates the implementation somewhat.  Therefore, too deep
 
885
// recursion cannot always be avoided.  This case is detected, and the failure
 
886
// flag is set, a signal to the caller that the string should be flattened and
 
887
// the operation retried.
 
888
int Utf8LengthHelper(String* input,
 
889
                     int from,
 
890
                     int to,
 
891
                     bool followed_by_surrogate,
 
892
                     int max_recursion,
 
893
                     bool* failure,
 
894
                     bool* starts_with_surrogate) {
 
895
  if (from == to) return 0;
 
896
  int total = 0;
 
897
  bool dummy;
 
898
  while (true) {
 
899
    if (input->IsAsciiRepresentation()) {
 
900
      *starts_with_surrogate = false;
 
901
      return total + to - from;
 
902
    }
 
903
    switch (StringShape(input).representation_tag()) {
 
904
      case kConsStringTag: {
 
905
        ConsString* str = ConsString::cast(input);
 
906
        String* first = str->first();
 
907
        String* second = str->second();
 
908
        int first_length = first->length();
 
909
        if (first_length - from > to - first_length) {
 
910
          if (first_length < to) {
 
911
            // Right hand side is shorter.  No need to check the recursion depth
 
912
            // since this can only happen log(n) times.
 
913
            bool right_starts_with_surrogate = false;
 
914
            total += Utf8LengthHelper(second,
 
915
                                      0,
 
916
                                      to - first_length,
 
917
                                      followed_by_surrogate,
 
918
                                      max_recursion - 1,
 
919
                                      failure,
 
920
                                      &right_starts_with_surrogate);
 
921
            if (*failure) return 0;
 
922
            followed_by_surrogate = right_starts_with_surrogate;
 
923
            input = first;
 
924
            to = first_length;
 
925
          } else {
 
926
            // We only need the left hand side.
 
927
            input = first;
 
928
          }
 
929
        } else {
 
930
          if (first_length > from) {
 
931
            // Left hand side is shorter.
 
932
            if (first->IsAsciiRepresentation()) {
 
933
              total += first_length - from;
 
934
              *starts_with_surrogate = false;
 
935
              starts_with_surrogate = &dummy;
 
936
              input = second;
 
937
              from = 0;
 
938
              to -= first_length;
 
939
            } else if (second->IsAsciiRepresentation()) {
 
940
              followed_by_surrogate = false;
 
941
              total += to - first_length;
 
942
              input = first;
 
943
              to = first_length;
 
944
            } else if (max_recursion > 0) {
 
945
              bool right_starts_with_surrogate = false;
 
946
              // Recursing on the long one.  This may fail.
 
947
              total += Utf8LengthHelper(second,
 
948
                                        0,
 
949
                                        to - first_length,
 
950
                                        followed_by_surrogate,
 
951
                                        max_recursion - 1,
 
952
                                        failure,
 
953
                                        &right_starts_with_surrogate);
 
954
              if (*failure) return 0;
 
955
              input = first;
 
956
              to = first_length;
 
957
              followed_by_surrogate = right_starts_with_surrogate;
 
958
            } else {
 
959
              *failure = true;
 
960
              return 0;
 
961
            }
 
962
          } else {
 
963
            // We only need the right hand side.
 
964
            input = second;
 
965
            from = 0;
 
966
            to -= first_length;
 
967
          }
 
968
        }
 
969
        continue;
 
970
      }
 
971
      case kExternalStringTag:
 
972
      case kSeqStringTag: {
 
973
        Vector<const uc16> vector = input->GetFlatContent().ToUC16Vector();
 
974
        const uc16* p = vector.start();
 
975
        int previous = unibrow::Utf16::kNoPreviousCharacter;
 
976
        for (int i = from; i < to; i++) {
 
977
          uc16 c = p[i];
 
978
          total += unibrow::Utf8::Length(c, previous);
 
979
          previous = c;
 
980
        }
 
981
        if (to - from > 0) {
 
982
          if (unibrow::Utf16::IsLeadSurrogate(previous) &&
 
983
              followed_by_surrogate) {
 
984
            total -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
 
985
          }
 
986
          if (unibrow::Utf16::IsTrailSurrogate(p[from])) {
 
987
            *starts_with_surrogate = true;
 
988
          }
 
989
        }
 
990
        return total;
 
991
      }
 
992
      case kSlicedStringTag: {
 
993
        SlicedString* str = SlicedString::cast(input);
 
994
        int offset = str->offset();
 
995
        input = str->parent();
 
996
        from += offset;
 
997
        to += offset;
 
998
        continue;
 
999
      }
 
1000
      default:
 
1001
        break;
 
1002
    }
 
1003
    UNREACHABLE();
 
1004
    return 0;
 
1005
  }
 
1006
  return 0;
 
1007
}
 
1008
 
 
1009
 
 
1010
int Utf8Length(Handle<String> str) {
 
1011
  bool dummy;
 
1012
  bool failure;
 
1013
  int len;
 
1014
  const int kRecursionBudget = 100;
 
1015
  do {
 
1016
    failure = false;
 
1017
    len = Utf8LengthHelper(
 
1018
        *str, 0, str->length(), false, kRecursionBudget, &failure, &dummy);
 
1019
    if (failure) FlattenString(str);
 
1020
  } while (failure);
 
1021
  return len;
 
1022
}
 
1023
 
 
1024
 
 
1025
DeferredHandleScope::DeferredHandleScope(Isolate* isolate)
 
1026
    : impl_(isolate->handle_scope_implementer()) {
 
1027
  ASSERT(impl_->isolate() == Isolate::Current());
 
1028
  impl_->BeginDeferredScope();
 
1029
  v8::ImplementationUtilities::HandleScopeData* data =
 
1030
      impl_->isolate()->handle_scope_data();
 
1031
  Object** new_next = impl_->GetSpareOrNewBlock();
 
1032
  Object** new_limit = &new_next[kHandleBlockSize];
 
1033
  ASSERT(data->limit == &impl_->blocks()->last()[kHandleBlockSize]);
 
1034
  impl_->blocks()->Add(new_next);
 
1035
 
 
1036
#ifdef DEBUG
 
1037
  prev_level_ = data->level;
 
1038
#endif
 
1039
  data->level++;
 
1040
  prev_limit_ = data->limit;
 
1041
  prev_next_ = data->next;
 
1042
  data->next = new_next;
 
1043
  data->limit = new_limit;
 
1044
}
 
1045
 
 
1046
 
 
1047
DeferredHandleScope::~DeferredHandleScope() {
 
1048
  impl_->isolate()->handle_scope_data()->level--;
 
1049
  ASSERT(handles_detached_);
 
1050
  ASSERT(impl_->isolate()->handle_scope_data()->level == prev_level_);
 
1051
}
 
1052
 
 
1053
 
 
1054
DeferredHandles* DeferredHandleScope::Detach() {
 
1055
  DeferredHandles* deferred = impl_->Detach(prev_limit_);
 
1056
  v8::ImplementationUtilities::HandleScopeData* data =
 
1057
      impl_->isolate()->handle_scope_data();
 
1058
  data->next = prev_next_;
 
1059
  data->limit = prev_limit_;
 
1060
#ifdef DEBUG
 
1061
  handles_detached_ = true;
 
1062
#endif
 
1063
  return deferred;
 
1064
}
 
1065
 
945
1066
 
946
1067
} }  // namespace v8::internal