@@ -208,6 +208,7 @@ inline bool PrototypeHasNoElements(PrototypeIterator* iter) {
208
208
JSObject* current = iter->GetCurrent <JSObject>();
209
209
if (current->IsAccessCheckNeeded ()) return false ;
210
210
if (current->HasIndexedInterceptor ()) return false ;
211
+ if (current->IsJSValue ()) return false ;
211
212
if (current->elements ()->length () != 0 ) return false ;
212
213
}
213
214
return true ;
@@ -232,6 +233,41 @@ inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
232
233
}
233
234
234
235
236
+ inline bool HasSimpleElements (JSObject* current) {
237
+ if (current->IsAccessCheckNeeded ()) return false ;
238
+ if (current->HasIndexedInterceptor ()) return false ;
239
+ if (current->IsJSValue ()) return false ;
240
+ if (current->GetElementsAccessor ()->HasAccessors (current)) return false ;
241
+ return true ;
242
+ }
243
+
244
+
245
+ inline bool HasOnlySimpleReceiverElements (Isolate* isolate,
246
+ JSReceiver* receiver) {
247
+ // Check that we have no accessors on the receiver's elements.
248
+ JSObject* object = JSObject::cast (receiver);
249
+ if (!HasSimpleElements (object)) return false ;
250
+ // Check that ther are not elements on the prototype.
251
+ DisallowHeapAllocation no_gc;
252
+ PrototypeIterator iter (isolate, receiver);
253
+ return PrototypeHasNoElements (&iter);
254
+ }
255
+
256
+
257
+ inline bool HasOnlySimpleElements (Isolate* isolate, JSReceiver* receiver) {
258
+ // Check that ther are not elements on the prototype.
259
+ DisallowHeapAllocation no_gc;
260
+ PrototypeIterator iter (isolate, receiver,
261
+ PrototypeIterator::START_AT_RECEIVER);
262
+ for (; !iter.IsAtEnd (); iter.Advance ()) {
263
+ if (iter.GetCurrent ()->IsJSProxy ()) return false ;
264
+ JSObject* current = iter.GetCurrent <JSObject>();
265
+ if (!HasSimpleElements (current)) return false ;
266
+ }
267
+ return true ;
268
+ }
269
+
270
+
235
271
// Returns empty handle if not applicable.
236
272
MUST_USE_RESULT
237
273
inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements (
@@ -1013,9 +1049,10 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
1013
1049
if (!val->ToUint32 (&length)) {
1014
1050
length = 0 ;
1015
1051
}
1052
+ return IterateElementsSlow (isolate, receiver, length, visitor);
1016
1053
}
1017
1054
1018
- if (!(receiver-> IsJSArray () || receiver-> IsJSTypedArray () )) {
1055
+ if (!HasOnlySimpleElements (isolate, * receiver)) {
1019
1056
// For classes which are not known to be safe to access via elements alone,
1020
1057
// use the slow case.
1021
1058
return IterateElementsSlow (isolate, receiver, length, visitor);
@@ -1031,7 +1068,7 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
1031
1068
// to check the prototype for missing elements.
1032
1069
Handle<FixedArray> elements (FixedArray::cast (array->elements ()));
1033
1070
int fast_length = static_cast <int >(length);
1034
- DCHECK (fast_length <= elements->length ());
1071
+ DCHECK_LE (fast_length, elements->length ());
1035
1072
for (int j = 0 ; j < fast_length; j++) {
1036
1073
HandleScope loop_scope (isolate);
1037
1074
Handle<Object> element_value (elements->get (j), isolate);
@@ -1090,14 +1127,6 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
1090
1127
break ;
1091
1128
}
1092
1129
case DICTIONARY_ELEMENTS: {
1093
- // CollectElementIndices() can't be called when there's a JSProxy
1094
- // on the prototype chain.
1095
- for (PrototypeIterator iter (isolate, array); !iter.IsAtEnd ();
1096
- iter.Advance ()) {
1097
- if (PrototypeIterator::GetCurrent (iter)->IsJSProxy ()) {
1098
- return IterateElementsSlow (isolate, array, length, visitor);
1099
- }
1100
- }
1101
1130
Handle<SeededNumberDictionary> dict (array->element_dictionary ());
1102
1131
List<uint32_t > indices (dict->Capacity () / 2 );
1103
1132
// Collect all indices in the object and the prototypes less
@@ -1187,7 +1216,6 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
1187
1216
1188
1217
1189
1218
bool HasConcatSpreadableModifier (Isolate* isolate, Handle<JSArray> obj) {
1190
- DCHECK (isolate->IsFastArrayConstructorPrototypeChainIntact ());
1191
1219
if (!FLAG_harmony_concat_spreadable) return false ;
1192
1220
Handle<Symbol> key (isolate->factory ()->is_concat_spreadable_symbol ());
1193
1221
Maybe<bool > maybe = JSReceiver::HasProperty (obj, key);
@@ -1232,17 +1260,14 @@ Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
1232
1260
length_estimate = static_cast <uint32_t >(array->length ()->Number ());
1233
1261
if (length_estimate != 0 ) {
1234
1262
ElementsKind array_kind =
1235
- GetPackedElementsKind (array->map ()-> elements_kind ());
1263
+ GetPackedElementsKind (array->GetElementsKind ());
1236
1264
kind = GetMoreGeneralElementsKind (kind, array_kind);
1237
1265
}
1238
1266
element_estimate = EstimateElementCount (array);
1239
1267
} else {
1240
1268
if (obj->IsHeapObject ()) {
1241
- if (obj->IsNumber ()) {
1242
- kind = GetMoreGeneralElementsKind (kind, FAST_DOUBLE_ELEMENTS);
1243
- } else {
1244
- kind = GetMoreGeneralElementsKind (kind, FAST_ELEMENTS);
1245
- }
1269
+ kind = GetMoreGeneralElementsKind (
1270
+ kind, obj->IsNumber () ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS);
1246
1271
}
1247
1272
length_estimate = 1 ;
1248
1273
element_estimate = 1 ;
@@ -1284,7 +1309,7 @@ Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
1284
1309
} else {
1285
1310
JSArray* array = JSArray::cast (*obj);
1286
1311
uint32_t length = static_cast <uint32_t >(array->length ()->Number ());
1287
- switch (array->map ()-> elements_kind ()) {
1312
+ switch (array->GetElementsKind ()) {
1288
1313
case FAST_HOLEY_DOUBLE_ELEMENTS:
1289
1314
case FAST_DOUBLE_ELEMENTS: {
1290
1315
// Empty array is FixedArray but not FixedDoubleArray.
@@ -1335,14 +1360,7 @@ Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
1335
1360
}
1336
1361
}
1337
1362
if (!failure) {
1338
- Handle<JSArray> array = isolate->factory ()->NewJSArray (0 );
1339
- Smi* length = Smi::FromInt (j);
1340
- Handle<Map> map;
1341
- map = JSObject::GetElementsTransitionMap (array, kind);
1342
- array->set_map (*map);
1343
- array->set_length (length);
1344
- array->set_elements (*storage);
1345
- return *array;
1363
+ return *isolate->factory ()->NewJSArrayWithElements (storage, kind, j);
1346
1364
}
1347
1365
// In case of failure, fall through.
1348
1366
}
@@ -1387,23 +1405,23 @@ Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
1387
1405
1388
1406
1389
1407
MaybeHandle<JSArray> Fast_ArrayConcat (Isolate* isolate, Arguments* args) {
1390
- if (!isolate->IsFastArrayConstructorPrototypeChainIntact ()) {
1391
- return MaybeHandle<JSArray>();
1392
- }
1393
1408
int n_arguments = args->length ();
1394
1409
int result_len = 0 ;
1395
1410
{
1396
1411
DisallowHeapAllocation no_gc;
1397
- Object* array_proto = isolate->array_function ()->prototype ();
1398
1412
// Iterate through all the arguments performing checks
1399
1413
// and calculating total length.
1400
1414
for (int i = 0 ; i < n_arguments; i++) {
1401
1415
Object* arg = (*args)[i];
1402
1416
if (!arg->IsJSArray ()) return MaybeHandle<JSArray>();
1417
+ if (!HasOnlySimpleReceiverElements (isolate, JSObject::cast (arg))) {
1418
+ return MaybeHandle<JSArray>();
1419
+ }
1420
+ // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS.
1421
+ if (!JSObject::cast (arg)->HasFastElements ()) {
1422
+ return MaybeHandle<JSArray>();
1423
+ }
1403
1424
Handle<JSArray> array (JSArray::cast (arg), isolate);
1404
- if (!array->HasFastElements ()) return MaybeHandle<JSArray>();
1405
- PrototypeIterator iter (isolate, arg);
1406
- if (iter.GetCurrent () != array_proto) return MaybeHandle<JSArray>();
1407
1425
if (HasConcatSpreadableModifier (isolate, array)) {
1408
1426
return MaybeHandle<JSArray>();
1409
1427
}
@@ -2207,7 +2225,11 @@ BUILTIN(DateConstructor) {
2207
2225
char buffer[128 ];
2208
2226
Vector<char > str (buffer, arraysize (buffer));
2209
2227
ToDateString (time_val, str, isolate->date_cache ());
2210
- return *isolate->factory ()->NewStringFromAsciiChecked (str.start ());
2228
+ Handle<String> result;
2229
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION (
2230
+ isolate, result,
2231
+ isolate->factory ()->NewStringFromUtf8 (CStrVector (buffer)));
2232
+ return *result;
2211
2233
}
2212
2234
2213
2235
@@ -2787,7 +2809,11 @@ BUILTIN(DatePrototypeToDateString) {
2787
2809
char buffer[128 ];
2788
2810
Vector<char > str (buffer, arraysize (buffer));
2789
2811
ToDateString (date->value ()->Number (), str, isolate->date_cache (), kDateOnly );
2790
- return *isolate->factory ()->NewStringFromAsciiChecked (str.start ());
2812
+ Handle<String> result;
2813
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION (
2814
+ isolate, result,
2815
+ isolate->factory ()->NewStringFromUtf8 (CStrVector (buffer)));
2816
+ return *result;
2791
2817
}
2792
2818
2793
2819
@@ -2827,7 +2853,11 @@ BUILTIN(DatePrototypeToString) {
2827
2853
char buffer[128 ];
2828
2854
Vector<char > str (buffer, arraysize (buffer));
2829
2855
ToDateString (date->value ()->Number (), str, isolate->date_cache ());
2830
- return *isolate->factory ()->NewStringFromAsciiChecked (str.start ());
2856
+ Handle<String> result;
2857
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION (
2858
+ isolate, result,
2859
+ isolate->factory ()->NewStringFromUtf8 (CStrVector (buffer)));
2860
+ return *result;
2831
2861
}
2832
2862
2833
2863
@@ -2838,7 +2868,11 @@ BUILTIN(DatePrototypeToTimeString) {
2838
2868
char buffer[128 ];
2839
2869
Vector<char > str (buffer, arraysize (buffer));
2840
2870
ToDateString (date->value ()->Number (), str, isolate->date_cache (), kTimeOnly );
2841
- return *isolate->factory ()->NewStringFromAsciiChecked (str.start ());
2871
+ Handle<String> result;
2872
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION (
2873
+ isolate, result,
2874
+ isolate->factory ()->NewStringFromUtf8 (CStrVector (buffer)));
2875
+ return *result;
2842
2876
}
2843
2877
2844
2878
0 commit comments